blob: 93e9bb0821653a0bcd8a16bf9cd84e8a57392066 [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
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000298void RTCPSender::SetSSRC(uint32_t ssrc) {
danilchap56036ff2016-03-22 11:14:09 -0700299 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000300
Erik Språng242e22b2015-05-11 10:17:43 +0200301 if (ssrc_ != 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200302 // not first SetSSRC, probably due to a collision
303 // schedule a new RTCP report
304 // make sure that we send a RTP packet
Erik Språng242e22b2015-05-11 10:17:43 +0200305 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
Erik Språng61be2a42015-04-27 13:32:52 +0200306 }
Erik Språng242e22b2015-05-11 10:17:43 +0200307 ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000308}
309
Erik Språng61be2a42015-04-27 13:32:52 +0200310void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
danilchap56036ff2016-03-22 11:14:09 -0700311 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200312 remote_ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000313}
314
Peter Boström9ba52f82015-06-01 14:12:28 +0200315int32_t RTCPSender::SetCNAME(const char* c_name) {
316 if (!c_name)
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000317 return -1;
318
kwiberg352444f2016-11-28 15:58:53 -0800319 RTC_DCHECK_LT(strlen(c_name), RTCP_CNAME_SIZE);
danilchap56036ff2016-03-22 11:14:09 -0700320 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200321 cname_ = c_name;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000322 return 0;
323}
324
Erik Språng0ea42d32015-06-25 14:46:16 +0200325int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC, const char* c_name) {
danilchap56036ff2016-03-22 11:14:09 -0700326 RTC_DCHECK(c_name);
kwiberg352444f2016-11-28 15:58:53 -0800327 RTC_DCHECK_LT(strlen(c_name), RTCP_CNAME_SIZE);
danilchap56036ff2016-03-22 11:14:09 -0700328 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap74e8df8f2017-03-16 08:04:08 -0700329 // One spot is reserved for ssrc_/cname_.
330 // TODO(danilchap): Add support for more than 30 contributes by sending
331 // several sdes packets.
332 if (csrc_cnames_.size() >= rtcp::Sdes::kMaxNumberOfChunks - 1)
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000333 return -1;
Erik Språng0ea42d32015-06-25 14:46:16 +0200334
335 csrc_cnames_[SSRC] = c_name;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000336 return 0;
337}
338
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000339int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
danilchap56036ff2016-03-22 11:14:09 -0700340 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200341 auto it = csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000342
Erik Språng242e22b2015-05-11 10:17:43 +0200343 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000344 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200345
Erik Språng242e22b2015-05-11 10:17:43 +0200346 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000347 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000348}
349
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000350bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
danilchap162abd32015-12-10 02:39:40 -0800351 /*
352 For audio we use a fix 5 sec interval
niklase@google.com470e71d2011-07-07 08:21:25 +0000353
danilchap162abd32015-12-10 02:39:40 -0800354 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
355 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
356 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000357
358
danilchap162abd32015-12-10 02:39:40 -0800359 From RFC 3550
niklase@google.com470e71d2011-07-07 08:21:25 +0000360
danilchap162abd32015-12-10 02:39:40 -0800361 MAX RTCP BW is 5% if the session BW
362 A send report is approximately 65 bytes inc CNAME
363 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000364
danilchap162abd32015-12-10 02:39:40 -0800365 The RECOMMENDED value for the reduced minimum in seconds is 360
366 divided by the session bandwidth in kilobits/second. This minimum
367 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
niklase@google.com470e71d2011-07-07 08:21:25 +0000368
danilchap162abd32015-12-10 02:39:40 -0800369 If the participant has not yet sent an RTCP packet (the variable
370 initial is true), the constant Tmin is set to 2.5 seconds, else it
371 is set to 5 seconds.
niklase@google.com470e71d2011-07-07 08:21:25 +0000372
danilchap162abd32015-12-10 02:39:40 -0800373 The interval between RTCP packets is varied randomly over the
374 range [0.5,1.5] times the calculated interval to avoid unintended
375 synchronization of all participants
niklase@google.com470e71d2011-07-07 08:21:25 +0000376
danilchap162abd32015-12-10 02:39:40 -0800377 if we send
378 If the participant is a sender (we_sent true), the constant C is
379 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
380 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
381 number of senders.
niklase@google.com470e71d2011-07-07 08:21:25 +0000382
danilchap162abd32015-12-10 02:39:40 -0800383 if we receive only
384 If we_sent is not true, the constant C is set
385 to the average RTCP packet size divided by 75% of the RTCP
386 bandwidth. The constant n is set to the number of receivers
387 (members - senders). If the number of senders is greater than
388 25%, senders and receivers are treated together.
niklase@google.com470e71d2011-07-07 08:21:25 +0000389
danilchap162abd32015-12-10 02:39:40 -0800390 reconsideration NOT required for peer-to-peer
391 "timer reconsideration" is
392 employed. This algorithm implements a simple back-off mechanism
393 which causes users to hold back RTCP packet transmission if the
394 group sizes are increasing.
niklase@google.com470e71d2011-07-07 08:21:25 +0000395
danilchap162abd32015-12-10 02:39:40 -0800396 n = number of members
397 C = avg_size/(rtcpBW/4)
niklase@google.com470e71d2011-07-07 08:21:25 +0000398
danilchap162abd32015-12-10 02:39:40 -0800399 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
niklase@google.com470e71d2011-07-07 08:21:25 +0000400
danilchap162abd32015-12-10 02:39:40 -0800401 4. The calculated interval T is set to a number uniformly distributed
402 between 0.5 and 1.5 times the deterministic calculated interval.
niklase@google.com470e71d2011-07-07 08:21:25 +0000403
danilchap162abd32015-12-10 02:39:40 -0800404 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
405 for the fact that the timer reconsideration algorithm converges to
406 a value of the RTCP bandwidth below the intended average
407 */
niklase@google.com470e71d2011-07-07 08:21:25 +0000408
Erik Språng242e22b2015-05-11 10:17:43 +0200409 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000410
danilchap56036ff2016-03-22 11:14:09 -0700411 rtc::CritScope lock(&critical_section_rtcp_sender_);
xians@webrtc.org8738d272011-11-25 13:43:53 +0000412
pbosda903ea2015-10-02 02:36:56 -0700413 if (method_ == RtcpMode::kOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000414 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000415
Erik Språng242e22b2015-05-11 10:17:43 +0200416 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200417 // for video key-frames we want to send the RTCP before the large key-frame
418 // if we have a 100 ms margin
419 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
420 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000421
Erik Språng242e22b2015-05-11 10:17:43 +0200422 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200423 return true;
424 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200425 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200426 // wrap
427 return true;
428 }
429 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000430}
431
danilchap56036ff2016-03-22 11:14:09 -0700432std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSR(const RtcpContext& ctx) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200433 // Timestamp shouldn't be estimated before first media frame.
434 RTC_DCHECK_GE(last_frame_capture_time_ms_, 0);
Erik Språng61be2a42015-04-27 13:32:52 +0200435 // The timestamp of this RTCP packet should be estimated as the timestamp of
436 // the frame being captured at this moment. We are calculating that
437 // timestamp as the last frame's timestamp + the time since the last frame
438 // was captured.
solenbergb19d2882016-10-03 06:22:25 -0700439 uint32_t rtp_rate =
440 (audio_ ? kBogusRtpRateForAudioRtcp : kVideoPayloadTypeFrequency) / 1000;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200441 uint32_t rtp_timestamp =
danilchap71fead22016-08-18 02:01:49 -0700442 timestamp_offset_ + last_rtp_timestamp_ +
solenbergb19d2882016-10-03 06:22:25 -0700443 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) * rtp_rate;
niklase@google.com470e71d2011-07-07 08:21:25 +0000444
Erik Språngf7c57762015-12-04 10:40:35 +0100445 rtcp::SenderReport* report = new rtcp::SenderReport();
danilchap822a16f2016-09-27 09:27:47 -0700446 report->SetSenderSsrc(ssrc_);
danilchap51813b32016-12-16 02:44:36 -0800447 report->SetNtp(ctx.now_);
danilchap822a16f2016-09-27 09:27:47 -0700448 report->SetRtpTimestamp(rtp_timestamp);
449 report->SetPacketCount(ctx.feedback_state_.packets_sent);
450 report->SetOctetCount(ctx.feedback_state_.media_bytes_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000451
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200452 for (auto it : report_blocks_)
danilchap822a16f2016-09-27 09:27:47 -0700453 report->AddReportBlock(it.second);
niklase@google.com470e71d2011-07-07 08:21:25 +0000454
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200455 report_blocks_.clear();
Erik Språngf7c57762015-12-04 10:40:35 +0100456
danilchap56036ff2016-03-22 11:14:09 -0700457 return std::unique_ptr<rtcp::RtcpPacket>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000458}
459
danilchap56036ff2016-03-22 11:14:09 -0700460std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSDES(
Erik Språngf7c57762015-12-04 10:40:35 +0100461 const RtcpContext& ctx) {
Erik Språng0ea42d32015-06-25 14:46:16 +0200462 size_t length_cname = cname_.length();
kwiberg352444f2016-11-28 15:58:53 -0800463 RTC_CHECK_LT(length_cname, RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000464
Erik Språngf7c57762015-12-04 10:40:35 +0100465 rtcp::Sdes* sdes = new rtcp::Sdes();
danilchap822a16f2016-09-27 09:27:47 -0700466 sdes->AddCName(ssrc_, cname_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200467
danilchap74e8df8f2017-03-16 08:04:08 -0700468 for (const auto& it : csrc_cnames_)
469 RTC_CHECK(sdes->AddCName(it.first, it.second));
Erik Språng0ea42d32015-06-25 14:46:16 +0200470
danilchap56036ff2016-03-22 11:14:09 -0700471 return std::unique_ptr<rtcp::RtcpPacket>(sdes);
niklase@google.com470e71d2011-07-07 08:21:25 +0000472}
473
danilchap56036ff2016-03-22 11:14:09 -0700474std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildRR(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100475 rtcp::ReceiverReport* report = new rtcp::ReceiverReport();
danilchap822a16f2016-09-27 09:27:47 -0700476 report->SetSenderSsrc(ssrc_);
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200477 for (auto it : report_blocks_)
danilchap822a16f2016-09-27 09:27:47 -0700478 report->AddReportBlock(it.second);
Erik Språng61be2a42015-04-27 13:32:52 +0200479
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200480 report_blocks_.clear();
danilchap56036ff2016-03-22 11:14:09 -0700481 return std::unique_ptr<rtcp::RtcpPacket>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000482}
483
danilchap56036ff2016-03-22 11:14:09 -0700484std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildPLI(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100485 rtcp::Pli* pli = new rtcp::Pli();
danilchap822a16f2016-09-27 09:27:47 -0700486 pli->SetSenderSsrc(ssrc_);
487 pli->SetMediaSsrc(remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200488
Erik Språng242e22b2015-05-11 10:17:43 +0200489 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
490 "RTCPSender::PLI");
491 ++packet_type_counter_.pli_packets;
492 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
493 ssrc_, packet_type_counter_.pli_packets);
494
danilchap56036ff2016-03-22 11:14:09 -0700495 return std::unique_ptr<rtcp::RtcpPacket>(pli);
Erik Språng61be2a42015-04-27 13:32:52 +0200496}
497
danilchap56036ff2016-03-22 11:14:09 -0700498std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildFIR(const RtcpContext& ctx) {
danilchap498ee8e2017-02-08 05:24:31 -0800499 ++sequence_number_fir_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000500
Erik Språngf7c57762015-12-04 10:40:35 +0100501 rtcp::Fir* fir = new rtcp::Fir();
danilchap822a16f2016-09-27 09:27:47 -0700502 fir->SetSenderSsrc(ssrc_);
503 fir->AddRequestTo(remote_ssrc_, sequence_number_fir_);
Erik Språng242e22b2015-05-11 10:17:43 +0200504
505 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
506 "RTCPSender::FIR");
507 ++packet_type_counter_.fir_packets;
508 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
509 ssrc_, packet_type_counter_.fir_packets);
510
danilchap56036ff2016-03-22 11:14:09 -0700511 return std::unique_ptr<rtcp::RtcpPacket>(fir);
niklase@google.com470e71d2011-07-07 08:21:25 +0000512}
513
danilchap56036ff2016-03-22 11:14:09 -0700514std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildREMB(
Erik Språngf7c57762015-12-04 10:40:35 +0100515 const RtcpContext& ctx) {
516 rtcp::Remb* remb = new rtcp::Remb();
danilchap822a16f2016-09-27 09:27:47 -0700517 remb->SetSenderSsrc(ssrc_);
518 remb->SetBitrateBps(remb_bitrate_);
519 remb->SetSsrcs(remb_ssrcs_);
Erik Språng61be2a42015-04-27 13:32:52 +0200520
Erik Språng242e22b2015-05-11 10:17:43 +0200521 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
522 "RTCPSender::REMB");
523
danilchap56036ff2016-03-22 11:14:09 -0700524 return std::unique_ptr<rtcp::RtcpPacket>(remb);
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000525}
526
Erik Språng61be2a42015-04-27 13:32:52 +0200527void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
danilchap56036ff2016-03-22 11:14:09 -0700528 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap2b616392016-08-18 06:17:42 -0700529 tmmbr_send_bps_ = target_bitrate;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000530}
531
danilchap56036ff2016-03-22 11:14:09 -0700532std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBR(
Erik Språngf7c57762015-12-04 10:40:35 +0100533 const RtcpContext& ctx) {
534 if (ctx.feedback_state_.module == nullptr)
535 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200536 // Before sending the TMMBR check the received TMMBN, only an owner is
537 // allowed to raise the bitrate:
538 // * If the sender is an owner of the TMMBN -> send TMMBR
539 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000540
Erik Språng61be2a42015-04-27 13:32:52 +0200541 // get current bounding set from RTCP receiver
danilchap2b616392016-08-18 06:17:42 -0700542 bool tmmbr_owner = false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000543
Erik Språng242e22b2015-05-11 10:17:43 +0200544 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
545 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
Erik Språng61be2a42015-04-27 13:32:52 +0200546 // since RTCPreceiver is not doing the reverse we should be fine
danilchap2b616392016-08-18 06:17:42 -0700547 std::vector<rtcp::TmmbItem> candidates =
548 ctx.feedback_state_.module->BoundingSet(&tmmbr_owner);
niklase@google.com470e71d2011-07-07 08:21:25 +0000549
danilchap2b616392016-08-18 06:17:42 -0700550 if (!candidates.empty()) {
551 for (const auto& candidate : candidates) {
552 if (candidate.bitrate_bps() == tmmbr_send_bps_ &&
553 candidate.packet_overhead() == packet_oh_send_) {
Erik Språngf7c57762015-12-04 10:40:35 +0100554 // Do not send the same tuple.
555 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200556 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000557 }
danilchap2b616392016-08-18 06:17:42 -0700558 if (!tmmbr_owner) {
559 // Use received bounding set as candidate set.
560 // Add current tuple.
561 candidates.emplace_back(ssrc_, tmmbr_send_bps_, packet_oh_send_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000562
danilchap2b616392016-08-18 06:17:42 -0700563 // Find bounding set.
danilchap2f69ce92016-08-16 03:21:38 -0700564 std::vector<rtcp::TmmbItem> bounding =
565 TMMBRHelp::FindBoundingSet(std::move(candidates));
danilchap2b616392016-08-18 06:17:42 -0700566 tmmbr_owner = TMMBRHelp::IsOwner(bounding, ssrc_);
567 if (!tmmbr_owner) {
Erik Språngf7c57762015-12-04 10:40:35 +0100568 // Did not enter bounding set, no meaning to send this request.
569 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200570 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000571 }
Erik Språng61be2a42015-04-27 13:32:52 +0200572 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000573
danilchap2b616392016-08-18 06:17:42 -0700574 if (!tmmbr_send_bps_)
Erik Språngf7c57762015-12-04 10:40:35 +0100575 return nullptr;
sprang81a3e602015-08-21 05:30:11 -0700576
Erik Språngf7c57762015-12-04 10:40:35 +0100577 rtcp::Tmmbr* tmmbr = new rtcp::Tmmbr();
danilchap822a16f2016-09-27 09:27:47 -0700578 tmmbr->SetSenderSsrc(ssrc_);
danilchapf174e3a2016-02-05 04:56:36 -0800579 rtcp::TmmbItem request;
580 request.set_ssrc(remote_ssrc_);
danilchap2b616392016-08-18 06:17:42 -0700581 request.set_bitrate_bps(tmmbr_send_bps_);
danilchapf174e3a2016-02-05 04:56:36 -0800582 request.set_packet_overhead(packet_oh_send_);
danilchap822a16f2016-09-27 09:27:47 -0700583 tmmbr->AddTmmbr(request);
Erik Språngf7c57762015-12-04 10:40:35 +0100584
danilchap56036ff2016-03-22 11:14:09 -0700585 return std::unique_ptr<rtcp::RtcpPacket>(tmmbr);
Erik Språng61be2a42015-04-27 13:32:52 +0200586}
587
danilchap56036ff2016-03-22 11:14:09 -0700588std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBN(
Erik Språngf7c57762015-12-04 10:40:35 +0100589 const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100590 rtcp::Tmmbn* tmmbn = new rtcp::Tmmbn();
danilchap822a16f2016-09-27 09:27:47 -0700591 tmmbn->SetSenderSsrc(ssrc_);
danilchap6eaa3a42016-05-09 10:59:50 -0700592 for (const rtcp::TmmbItem& tmmbr : tmmbn_to_send_) {
593 if (tmmbr.bitrate_bps() > 0) {
danilchap822a16f2016-09-27 09:27:47 -0700594 tmmbn->AddTmmbr(tmmbr);
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000595 }
Erik Språng61be2a42015-04-27 13:32:52 +0200596 }
sprangd83df502015-08-27 01:05:08 -0700597
danilchap56036ff2016-03-22 11:14:09 -0700598 return std::unique_ptr<rtcp::RtcpPacket>(tmmbn);
niklase@google.com470e71d2011-07-07 08:21:25 +0000599}
600
danilchap56036ff2016-03-22 11:14:09 -0700601std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildAPP(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100602 rtcp::App* app = new rtcp::App();
danilchap822a16f2016-09-27 09:27:47 -0700603 app->SetSsrc(ssrc_);
604 app->SetSubType(app_sub_type_);
605 app->SetName(app_name_);
606 app->SetData(app_data_.get(), app_length_);
Erik Språng521875a2015-09-01 10:11:16 +0200607
danilchap56036ff2016-03-22 11:14:09 -0700608 return std::unique_ptr<rtcp::RtcpPacket>(app);
Erik Språng61be2a42015-04-27 13:32:52 +0200609}
610
danilchap56036ff2016-03-22 11:14:09 -0700611std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildNACK(
Erik Språngf7c57762015-12-04 10:40:35 +0100612 const RtcpContext& ctx) {
613 rtcp::Nack* nack = new rtcp::Nack();
danilchap822a16f2016-09-27 09:27:47 -0700614 nack->SetSenderSsrc(ssrc_);
615 nack->SetMediaSsrc(remote_ssrc_);
616 nack->SetPacketIds(ctx.nack_list_, ctx.nack_size_);
Erik Språng61be2a42015-04-27 13:32:52 +0200617
618 // Report stats.
619 NACKStringBuilder stringBuilder;
Erik Språngf7c57762015-12-04 10:40:35 +0100620 for (int idx = 0; idx < ctx.nack_size_; ++idx) {
621 stringBuilder.PushNACK(ctx.nack_list_[idx]);
622 nack_stats_.ReportRequest(ctx.nack_list_[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +0200623 }
Erik Språng61be2a42015-04-27 13:32:52 +0200624 packet_type_counter_.nack_requests = nack_stats_.requests();
625 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +0200626
627 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
628 "RTCPSender::NACK", "nacks",
629 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
630 ++packet_type_counter_.nack_packets;
631 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
632 ssrc_, packet_type_counter_.nack_packets);
633
danilchap56036ff2016-03-22 11:14:09 -0700634 return std::unique_ptr<rtcp::RtcpPacket>(nack);
Erik Språng61be2a42015-04-27 13:32:52 +0200635}
636
danilchap56036ff2016-03-22 11:14:09 -0700637std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildBYE(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100638 rtcp::Bye* bye = new rtcp::Bye();
danilchap822a16f2016-09-27 09:27:47 -0700639 bye->SetSenderSsrc(ssrc_);
640 bye->SetCsrcs(csrcs_);
sprangd8ee4f92015-08-24 03:25:19 -0700641
danilchap56036ff2016-03-22 11:14:09 -0700642 return std::unique_ptr<rtcp::RtcpPacket>(bye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000643}
644
sprang5e38c962016-12-01 05:18:09 -0800645std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildExtendedReports(
Erik Språngf7c57762015-12-04 10:40:35 +0100646 const RtcpContext& ctx) {
sprang5e38c962016-12-01 05:18:09 -0800647 std::unique_ptr<rtcp::ExtendedReports> xr(new rtcp::ExtendedReports());
danilchap822a16f2016-09-27 09:27:47 -0700648 xr->SetSenderSsrc(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000649
sprang5e38c962016-12-01 05:18:09 -0800650 if (!sending_ && xr_send_receiver_reference_time_enabled_) {
651 rtcp::Rrtr rrtr;
danilchap51813b32016-12-16 02:44:36 -0800652 rrtr.SetNtp(ctx.now_);
sprang5e38c962016-12-01 05:18:09 -0800653 xr->SetRrtr(rrtr);
654 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000655
sprang5e38c962016-12-01 05:18:09 -0800656 if (ctx.feedback_state_.has_last_xr_rr) {
657 xr->AddDlrrItem(ctx.feedback_state_.last_xr_rr);
658 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000659
sprang5e38c962016-12-01 05:18:09 -0800660 if (video_bitrate_allocation_) {
661 rtcp::TargetBitrate target_bitrate;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000662
sprang5e38c962016-12-01 05:18:09 -0800663 for (int sl = 0; sl < kMaxSpatialLayers; ++sl) {
664 for (int tl = 0; tl < kMaxTemporalStreams; ++tl) {
665 uint32_t layer_bitrate_bps =
666 video_bitrate_allocation_->GetBitrate(sl, tl);
667 if (layer_bitrate_bps > 0)
668 target_bitrate.AddTargetBitrate(sl, tl, layer_bitrate_bps / 1000);
669 }
670 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000671
sprang5e38c962016-12-01 05:18:09 -0800672 xr->SetTargetBitrate(target_bitrate);
673 video_bitrate_allocation_.reset();
674 }
Erik Språngca28fdc2015-08-31 14:00:50 +0200675
sprang5e38c962016-12-01 05:18:09 -0800676 if (xr_voip_metric_) {
677 rtcp::VoipMetric voip;
678 voip.SetMediaSsrc(remote_ssrc_);
679 voip.SetVoipMetric(*xr_voip_metric_);
680 xr_voip_metric_.reset();
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000681
sprang5e38c962016-12-01 05:18:09 -0800682 xr->SetVoipMetric(voip);
683 }
Erik Språngca28fdc2015-08-31 14:00:50 +0200684
sprang5e38c962016-12-01 05:18:09 -0800685 return std::move(xr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000686}
687
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000688int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200689 RTCPPacketType packetType,
690 int32_t nack_size,
nissecd386eb2017-03-14 08:54:43 -0700691 const uint16_t* nack_list) {
Erik Språng242e22b2015-05-11 10:17:43 +0200692 return SendCompoundRTCP(
693 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
nissecd386eb2017-03-14 08:54:43 -0700694 nack_size, nack_list);
Erik Språng242e22b2015-05-11 10:17:43 +0200695}
696
697int32_t RTCPSender::SendCompoundRTCP(
698 const FeedbackState& feedback_state,
Erik Språngf7c57762015-12-04 10:40:35 +0100699 const std::set<RTCPPacketType>& packet_types,
Erik Språng242e22b2015-05-11 10:17:43 +0200700 int32_t nack_size,
nissecd386eb2017-03-14 08:54:43 -0700701 const uint16_t* nack_list) {
terelius429c3452016-01-21 05:42:04 -0800702 PacketContainer container(transport_, event_log_);
nisse6f142eb2017-02-21 07:32:47 -0800703 size_t max_packet_size;
704
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000705 {
danilchap56036ff2016-03-22 11:14:09 -0700706 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbosda903ea2015-10-02 02:36:56 -0700707 if (method_ == RtcpMode::kOff) {
Erik Språng61be2a42015-04-27 13:32:52 +0200708 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
709 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +0000710 }
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200711 // Add all flags as volatile. Non volatile entries will not be overwritten.
712 // All new volatile flags added will be consumed by the end of this call.
713 SetFlags(packet_types, true);
714
715 // Prevent sending streams to send SR before any media has been sent.
716 const bool can_calculate_rtp_timestamp = (last_frame_capture_time_ms_ >= 0);
717 if (!can_calculate_rtp_timestamp) {
718 bool consumed_sr_flag = ConsumeFlag(kRtcpSr);
719 bool consumed_report_flag = sending_ && ConsumeFlag(kRtcpReport);
720 bool sender_report = consumed_report_flag || consumed_sr_flag;
721 if (sender_report && AllVolatileFlagsConsumed()) {
722 // This call was for Sender Report and nothing else.
723 return 0;
724 }
725 if (sending_ && method_ == RtcpMode::kCompound) {
726 // Not allowed to send any RTCP packet without sender report.
727 return -1;
728 }
729 }
730
731 if (packet_type_counter_.first_packet_time_ms == -1)
732 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språngf7c57762015-12-04 10:40:35 +0100733
734 // We need to send our NTP even if we haven't received any reports.
nissecd386eb2017-03-14 08:54:43 -0700735 RtcpContext context(feedback_state, nack_size, nack_list,
danilchap37953762017-02-09 11:15:25 -0800736 clock_->CurrentNtpTime());
Erik Språngf7c57762015-12-04 10:40:35 +0100737
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200738 PrepareReport(feedback_state);
Erik Språngf7c57762015-12-04 10:40:35 +0100739
danilchap56036ff2016-03-22 11:14:09 -0700740 std::unique_ptr<rtcp::RtcpPacket> packet_bye;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800741
Erik Språngf7c57762015-12-04 10:40:35 +0100742 auto it = report_flags_.begin();
743 while (it != report_flags_.end()) {
744 auto builder_it = builders_.find(it->type);
sprang5e38c962016-12-01 05:18:09 -0800745 RTC_DCHECK(builder_it != builders_.end())
746 << "Could not find builder for packet type " << it->type;
Erik Språngf7c57762015-12-04 10:40:35 +0100747 if (it->is_volatile) {
748 report_flags_.erase(it++);
749 } else {
750 ++it;
751 }
752
753 BuilderFunc func = builder_it->second;
danilchap56036ff2016-03-22 11:14:09 -0700754 std::unique_ptr<rtcp::RtcpPacket> packet = (this->*func)(context);
Erik Språngf7c57762015-12-04 10:40:35 +0100755 if (packet.get() == nullptr)
756 return -1;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800757 // If there is a BYE, don't append now - save it and append it
758 // at the end later.
759 if (builder_it->first == kRtcpBye) {
760 packet_bye = std::move(packet);
761 } else {
762 container.Append(packet.release());
763 }
764 }
765
766 // Append the BYE now at the end
767 if (packet_bye) {
768 container.Append(packet_bye.release());
Erik Språngf7c57762015-12-04 10:40:35 +0100769 }
770
771 if (packet_type_counter_observer_ != nullptr) {
772 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
773 remote_ssrc_, packet_type_counter_);
774 }
775
776 RTC_DCHECK(AllVolatileFlagsConsumed());
nisse6f142eb2017-02-21 07:32:47 -0800777 max_packet_size = max_packet_size_;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000778 }
Erik Språng61be2a42015-04-27 13:32:52 +0200779
nisse6f142eb2017-02-21 07:32:47 -0800780 size_t bytes_sent = container.SendPackets(max_packet_size);
Erik Språngf7c57762015-12-04 10:40:35 +0100781 return bytes_sent == 0 ? -1 : 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000782}
783
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200784void RTCPSender::PrepareReport(const FeedbackState& feedback_state) {
Erik Språng242e22b2015-05-11 10:17:43 +0200785 bool generate_report;
786 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
787 // Report type already explicitly set, don't automatically populate.
788 generate_report = true;
henrikg91d6ede2015-09-17 00:24:34 -0700789 RTC_DCHECK(ConsumeFlag(kRtcpReport) == false);
Erik Språng242e22b2015-05-11 10:17:43 +0200790 } else {
791 generate_report =
pbosda903ea2015-10-02 02:36:56 -0700792 (ConsumeFlag(kRtcpReport) && method_ == RtcpMode::kReducedSize) ||
793 method_ == RtcpMode::kCompound;
Erik Språng242e22b2015-05-11 10:17:43 +0200794 if (generate_report)
795 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000796 }
797
Erik Språng0ea42d32015-06-25 14:46:16 +0200798 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
Erik Språng242e22b2015-05-11 10:17:43 +0200799 SetFlag(kRtcpSdes, true);
800
Erik Språng242e22b2015-05-11 10:17:43 +0200801 if (generate_report) {
sprang5e38c962016-12-01 05:18:09 -0800802 if ((!sending_ && xr_send_receiver_reference_time_enabled_) ||
803 feedback_state.has_last_xr_rr || video_bitrate_allocation_) {
804 SetFlag(kRtcpAnyExtendedReports, true);
805 }
Erik Språng242e22b2015-05-11 10:17:43 +0200806
807 // generate next time to send an RTCP report
danilchap47a740b2015-12-15 00:30:07 -0800808 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000809
danilchap47a740b2015-12-15 00:30:07 -0800810 if (!audio_) {
Erik Språng242e22b2015-05-11 10:17:43 +0200811 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200812 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
813 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
814 if (send_bitrate_kbit != 0)
815 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000816 }
Erik Språng61be2a42015-04-27 13:32:52 +0200817 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
818 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
Erik Språng61be2a42015-04-27 13:32:52 +0200819 }
danilchap47a740b2015-12-15 00:30:07 -0800820 // The interval between RTCP packets is varied randomly over the
821 // range [1/2,3/2] times the calculated interval.
822 uint32_t timeToNext =
823 random_.Rand(minIntervalMs * 1 / 2, minIntervalMs * 3 / 2);
Erik Språng242e22b2015-05-11 10:17:43 +0200824 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000825
Per83d09102016-04-15 14:59:13 +0200826 if (receive_statistics_) {
827 StatisticianMap statisticians =
828 receive_statistics_->GetActiveStatisticians();
829 RTC_DCHECK(report_blocks_.empty());
830 for (auto& it : statisticians) {
831 AddReportBlock(feedback_state, it.first, it.second);
832 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000833 }
834 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000835}
836
danilchapa72e7342015-12-22 08:07:45 -0800837bool RTCPSender::AddReportBlock(const FeedbackState& feedback_state,
838 uint32_t ssrc,
839 StreamStatistician* statistician) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000840 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000841 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000842 if (!statistician->GetStatistics(&stats, true))
843 return false;
danilchapa72e7342015-12-22 08:07:45 -0800844
845 if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) {
846 LOG(LS_WARNING) << "Too many report blocks.";
847 return false;
848 }
849 RTC_DCHECK(report_blocks_.find(ssrc) == report_blocks_.end());
850 rtcp::ReportBlock* block = &report_blocks_[ssrc];
danilchap822a16f2016-09-27 09:27:47 -0700851 block->SetMediaSsrc(ssrc);
852 block->SetFractionLost(stats.fraction_lost);
853 if (!block->SetCumulativeLost(stats.cumulative_lost)) {
danilchapa72e7342015-12-22 08:07:45 -0800854 report_blocks_.erase(ssrc);
855 LOG(LS_WARNING) << "Cumulative lost is oversized.";
856 return false;
857 }
danilchap822a16f2016-09-27 09:27:47 -0700858 block->SetExtHighestSeqNum(stats.extended_max_sequence_number);
859 block->SetJitter(stats.jitter);
860 block->SetLastSr(feedback_state.remote_sr);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000861
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200862 // TODO(sprang): Do we really need separate time stamps for each report?
863 // Get our NTP as late as possible to avoid a race.
danilchap42287842017-02-20 06:40:18 -0800864 NtpTime ntp = clock_->CurrentNtpTime();
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000865
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200866 // Delay since last received report.
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000867 if ((feedback_state.last_rr_ntp_secs != 0) ||
868 (feedback_state.last_rr_ntp_frac != 0)) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200869 // Get the 16 lowest bits of seconds and the 16 highest bits of fractions.
danilchap42287842017-02-20 06:40:18 -0800870 uint32_t now = CompactNtp(ntp);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000871
Erik Språng61be2a42015-04-27 13:32:52 +0200872 uint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
873 receiveTime <<= 16;
874 receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000875
danilchap822a16f2016-09-27 09:27:47 -0700876 block->SetDelayLastSr(now - receiveTime);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000877 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000878 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000879}
880
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000881void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
kwiberg352444f2016-11-28 15:58:53 -0800882 RTC_DCHECK_LE(csrcs.size(), kRtpCsrcSize);
danilchap56036ff2016-03-22 11:14:09 -0700883 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000884 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +0000885}
886
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000887int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
888 uint32_t name,
889 const uint8_t* data,
890 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +0200891 if (length % 4 != 0) {
892 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
893 return -1;
894 }
danilchap56036ff2016-03-22 11:14:09 -0700895 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000896
Erik Språng242e22b2015-05-11 10:17:43 +0200897 SetFlag(kRtcpApp, true);
898 app_sub_type_ = subType;
899 app_name_ = name;
900 app_data_.reset(new uint8_t[length]);
901 app_length_ = length;
902 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +0200903 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000904}
905
spranga790d832016-12-02 07:29:44 -0800906// TODO(sprang): Remove support for VoIP metrics? (Not used in receiver.)
Erik Språng61be2a42015-04-27 13:32:52 +0200907int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
danilchap56036ff2016-03-22 11:14:09 -0700908 rtc::CritScope lock(&critical_section_rtcp_sender_);
sprang5e38c962016-12-01 05:18:09 -0800909 xr_voip_metric_.emplace(*VoIPMetric);
niklase@google.com470e71d2011-07-07 08:21:25 +0000910
sprang5e38c962016-12-01 05:18:09 -0800911 SetFlag(kRtcpAnyExtendedReports, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200912 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000913}
914
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000915void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700916 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200917 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000918}
919
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000920bool RTCPSender::RtcpXrReceiverReferenceTime() const {
danilchap56036ff2016-03-22 11:14:09 -0700921 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200922 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000923}
924
danilchap853ecb22016-08-22 08:26:15 -0700925void RTCPSender::SetTmmbn(std::vector<rtcp::TmmbItem> bounding_set) {
danilchap56036ff2016-03-22 11:14:09 -0700926 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap853ecb22016-08-22 08:26:15 -0700927 tmmbn_to_send_ = std::move(bounding_set);
danilchap6eaa3a42016-05-09 10:59:50 -0700928 SetFlag(kRtcpTmmbn, true);
niklase@google.com470e71d2011-07-07 08:21:25 +0000929}
Erik Språng61be2a42015-04-27 13:32:52 +0200930
sprang5e38c962016-12-01 05:18:09 -0800931void RTCPSender::SetFlag(uint32_t type, bool is_volatile) {
932 if (type & kRtcpAnyExtendedReports) {
933 report_flags_.insert(ReportFlag(kRtcpAnyExtendedReports, is_volatile));
934 } else {
935 report_flags_.insert(ReportFlag(type, is_volatile));
936 }
Erik Språng242e22b2015-05-11 10:17:43 +0200937}
938
939void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
940 bool is_volatile) {
941 for (RTCPPacketType type : types)
942 SetFlag(type, is_volatile);
943}
944
sprang5e38c962016-12-01 05:18:09 -0800945bool RTCPSender::IsFlagPresent(uint32_t type) const {
Erik Språng242e22b2015-05-11 10:17:43 +0200946 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
947}
948
sprang5e38c962016-12-01 05:18:09 -0800949bool RTCPSender::ConsumeFlag(uint32_t type, bool forced) {
Erik Språng242e22b2015-05-11 10:17:43 +0200950 auto it = report_flags_.find(ReportFlag(type, false));
951 if (it == report_flags_.end())
952 return false;
953 if (it->is_volatile || forced)
954 report_flags_.erase((it));
955 return true;
956}
957
958bool RTCPSender::AllVolatileFlagsConsumed() const {
959 for (const ReportFlag& flag : report_flags_) {
960 if (flag.is_volatile)
961 return false;
962 }
963 return true;
964}
965
sprang5e38c962016-12-01 05:18:09 -0800966void RTCPSender::SetVideoBitrateAllocation(const BitrateAllocation& bitrate) {
967 rtc::CritScope lock(&critical_section_rtcp_sender_);
968 video_bitrate_allocation_.emplace(bitrate);
969 SetFlag(kRtcpAnyExtendedReports, true);
970}
971
sprang233bd872015-09-08 13:25:16 -0700972bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
sprang233bd872015-09-08 13:25:16 -0700973 class Sender : public rtcp::RtcpPacket::PacketReadyCallback {
974 public:
terelius429c3452016-01-21 05:42:04 -0800975 Sender(Transport* transport, RtcEventLog* event_log)
976 : transport_(transport), event_log_(event_log), send_failure_(false) {}
sprang233bd872015-09-08 13:25:16 -0700977
978 void OnPacketReady(uint8_t* data, size_t length) override {
terelius429c3452016-01-21 05:42:04 -0800979 if (transport_->SendRtcp(data, length)) {
980 if (event_log_) {
981 event_log_->LogRtcpPacket(kOutgoingPacket, MediaType::ANY, data,
982 length);
983 }
984 } else {
sprang233bd872015-09-08 13:25:16 -0700985 send_failure_ = true;
terelius429c3452016-01-21 05:42:04 -0800986 }
sprang233bd872015-09-08 13:25:16 -0700987 }
988
989 Transport* const transport_;
terelius429c3452016-01-21 05:42:04 -0800990 RtcEventLog* const event_log_;
sprang233bd872015-09-08 13:25:16 -0700991 bool send_failure_;
terelius429c3452016-01-21 05:42:04 -0800992 // TODO(terelius): We would like to
993 // RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(Sender);
994 // but we can't because of an incorrect warning (C4822) in MVS 2013.
995 } sender(transport_, event_log_);
sprang233bd872015-09-08 13:25:16 -0700996
nisse6f142eb2017-02-21 07:32:47 -0800997 size_t max_packet_size;
stefanb77c7162017-02-06 06:29:38 -0800998 {
999 rtc::CritScope lock(&critical_section_rtcp_sender_);
1000 if (method_ == RtcpMode::kOff)
1001 return false;
nisse6f142eb2017-02-21 07:32:47 -08001002 max_packet_size = max_packet_size_;
stefanb77c7162017-02-06 06:29:38 -08001003 }
1004
nisse6f142eb2017-02-21 07:32:47 -08001005 RTC_DCHECK_LE(max_packet_size, IP_PACKET_SIZE);
sprang233bd872015-09-08 13:25:16 -07001006 uint8_t buffer[IP_PACKET_SIZE];
nisse6f142eb2017-02-21 07:32:47 -08001007 return packet.BuildExternalBuffer(buffer, max_packet_size, &sender) &&
sprang233bd872015-09-08 13:25:16 -07001008 !sender.send_failure_;
1009}
1010
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001011} // namespace webrtc