blob: 56d991c80fd4d457a945a9205c57c32c3b6ac2c2 [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()
80 : send_payload_type(0),
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +000081 packets_sent(0),
82 media_bytes_sent(0),
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000083 send_bitrate(0),
84 last_rr_ntp_secs(0),
85 last_rr_ntp_frac(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000086 remote_sr(0),
Erik Språng61be2a42015-04-27 13:32:52 +020087 has_last_xr_rr(false),
danilchap162abd32015-12-10 02:39:40 -080088 module(nullptr) {}
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000089
danilchap2f7dea12016-01-13 02:03:04 -080090class PacketContainer : public rtcp::CompoundPacket,
Erik Språngf7c57762015-12-04 10:40:35 +010091 public rtcp::RtcpPacket::PacketReadyCallback {
92 public:
terelius429c3452016-01-21 05:42:04 -080093 PacketContainer(Transport* transport, RtcEventLog* event_log)
94 : transport_(transport), event_log_(event_log), bytes_sent_(0) {}
Erik Språngf7c57762015-12-04 10:40:35 +010095 virtual ~PacketContainer() {
96 for (RtcpPacket* packet : appended_packets_)
97 delete packet;
98 }
99
100 void OnPacketReady(uint8_t* data, size_t length) override {
terelius429c3452016-01-21 05:42:04 -0800101 if (transport_->SendRtcp(data, length)) {
Erik Språngf7c57762015-12-04 10:40:35 +0100102 bytes_sent_ += length;
terelius429c3452016-01-21 05:42:04 -0800103 if (event_log_) {
104 event_log_->LogRtcpPacket(kOutgoingPacket, MediaType::ANY, data,
105 length);
106 }
107 }
Erik Språngf7c57762015-12-04 10:40:35 +0100108 }
109
danilchap41befce2016-03-30 11:11:51 -0700110 size_t SendPackets(size_t max_payload_length) {
kwiberg352444f2016-11-28 15:58:53 -0800111 RTC_DCHECK_LE(max_payload_length, IP_PACKET_SIZE);
danilchap41befce2016-03-30 11:11:51 -0700112 uint8_t buffer[IP_PACKET_SIZE];
113 BuildExternalBuffer(buffer, max_payload_length, this);
Erik Språngf7c57762015-12-04 10:40:35 +0100114 return bytes_sent_;
115 }
116
117 private:
118 Transport* transport_;
terelius429c3452016-01-21 05:42:04 -0800119 RtcEventLog* const event_log_;
Erik Språngf7c57762015-12-04 10:40:35 +0100120 size_t bytes_sent_;
terelius429c3452016-01-21 05:42:04 -0800121
122 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(PacketContainer);
Erik Språngf7c57762015-12-04 10:40:35 +0100123};
124
125class RTCPSender::RtcpContext {
126 public:
Erik Språng242e22b2015-05-11 10:17:43 +0200127 RtcpContext(const FeedbackState& feedback_state,
128 int32_t nack_size,
129 const uint16_t* nack_list,
danilchap51813b32016-12-16 02:44:36 -0800130 NtpTime now)
Erik Språngf7c57762015-12-04 10:40:35 +0100131 : feedback_state_(feedback_state),
132 nack_size_(nack_size),
133 nack_list_(nack_list),
danilchap51813b32016-12-16 02:44:36 -0800134 now_(now) {}
Erik Språng242e22b2015-05-11 10:17:43 +0200135
Erik Språngf7c57762015-12-04 10:40:35 +0100136 const FeedbackState& feedback_state_;
137 const int32_t nack_size_;
138 const uint16_t* nack_list_;
danilchap51813b32016-12-16 02:44:36 -0800139 const NtpTime now_;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200140};
141
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000142RTCPSender::RTCPSender(
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000143 bool audio,
144 Clock* clock,
145 ReceiveStatistics* receive_statistics,
sprang86fd9ed2015-09-29 04:45:43 -0700146 RtcpPacketTypeCounterObserver* packet_type_counter_observer,
terelius429c3452016-01-21 05:42:04 -0800147 RtcEventLog* event_log,
sprang86fd9ed2015-09-29 04:45:43 -0700148 Transport* outgoing_transport)
Peter Boströmac547a62015-09-17 23:03:57 +0200149 : audio_(audio),
Erik Språng242e22b2015-05-11 10:17:43 +0200150 clock_(clock),
danilchap47a740b2015-12-15 00:30:07 -0800151 random_(clock_->TimeInMicroseconds()),
pbosda903ea2015-10-02 02:36:56 -0700152 method_(RtcpMode::kOff),
terelius429c3452016-01-21 05:42:04 -0800153 event_log_(event_log),
sprang86fd9ed2015-09-29 04:45:43 -0700154 transport_(outgoing_transport),
Erik Språng242e22b2015-05-11 10:17:43 +0200155 using_nack_(false),
156 sending_(false),
157 remb_enabled_(false),
Erik Språng242e22b2015-05-11 10:17:43 +0200158 next_time_to_send_rtcp_(0),
danilchap71fead22016-08-18 02:01:49 -0700159 timestamp_offset_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000160 last_rtp_timestamp_(0),
161 last_frame_capture_time_ms_(-1),
Erik Språng242e22b2015-05-11 10:17:43 +0200162 ssrc_(0),
163 remote_ssrc_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000164 receive_statistics_(receive_statistics),
niklase@google.com470e71d2011-07-07 08:21:25 +0000165
Erik Språng242e22b2015-05-11 10:17:43 +0200166 sequence_number_fir_(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000167
Erik Språng242e22b2015-05-11 10:17:43 +0200168 remb_bitrate_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000169
danilchap2b616392016-08-18 06:17:42 -0700170 tmmbr_send_bps_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200171 packet_oh_send_(0),
nisse284542b2017-01-10 08:58:32 -0800172 max_packet_size_(IP_PACKET_SIZE - 28), // IPv4 + UDP by default.
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000173
Erik Språng242e22b2015-05-11 10:17:43 +0200174 app_sub_type_(0),
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200175 app_name_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200176 app_data_(nullptr),
177 app_length_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000178
Erik Språng242e22b2015-05-11 10:17:43 +0200179 xr_send_receiver_reference_time_enabled_(false),
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000180 packet_type_counter_observer_(packet_type_counter_observer) {
sprang86fd9ed2015-09-29 04:45:43 -0700181 RTC_DCHECK(transport_ != nullptr);
Erik Språng242e22b2015-05-11 10:17:43 +0200182
183 builders_[kRtcpSr] = &RTCPSender::BuildSR;
184 builders_[kRtcpRr] = &RTCPSender::BuildRR;
Erik Språng0ea42d32015-06-25 14:46:16 +0200185 builders_[kRtcpSdes] = &RTCPSender::BuildSDES;
Erik Språng242e22b2015-05-11 10:17:43 +0200186 builders_[kRtcpPli] = &RTCPSender::BuildPLI;
187 builders_[kRtcpFir] = &RTCPSender::BuildFIR;
Erik Språng242e22b2015-05-11 10:17:43 +0200188 builders_[kRtcpRemb] = &RTCPSender::BuildREMB;
189 builders_[kRtcpBye] = &RTCPSender::BuildBYE;
190 builders_[kRtcpApp] = &RTCPSender::BuildAPP;
191 builders_[kRtcpTmmbr] = &RTCPSender::BuildTMMBR;
192 builders_[kRtcpTmmbn] = &RTCPSender::BuildTMMBN;
193 builders_[kRtcpNack] = &RTCPSender::BuildNACK;
sprang5e38c962016-12-01 05:18:09 -0800194 builders_[kRtcpAnyExtendedReports] = &RTCPSender::BuildExtendedReports;
niklase@google.com470e71d2011-07-07 08:21:25 +0000195}
196
danilchap162abd32015-12-10 02:39:40 -0800197RTCPSender::~RTCPSender() {}
niklase@google.com470e71d2011-07-07 08:21:25 +0000198
pbosda903ea2015-10-02 02:36:56 -0700199RtcpMode RTCPSender::Status() const {
danilchap56036ff2016-03-22 11:14:09 -0700200 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200201 return method_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000202}
203
skvlad1c392cc2016-04-01 14:46:44 -0700204void RTCPSender::SetRTCPStatus(RtcpMode new_method) {
danilchap56036ff2016-03-22 11:14:09 -0700205 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000206
skvlad1c392cc2016-04-01 14:46:44 -0700207 if (method_ == RtcpMode::kOff && new_method != RtcpMode::kOff) {
208 // When switching on, reschedule the next packet
209 next_time_to_send_rtcp_ =
Erik Språng242e22b2015-05-11 10:17:43 +0200210 clock_->TimeInMilliseconds() +
211 (audio_ ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
skvlad1c392cc2016-04-01 14:46:44 -0700212 }
213 method_ = new_method;
niklase@google.com470e71d2011-07-07 08:21:25 +0000214}
215
Erik Språng61be2a42015-04-27 13:32:52 +0200216bool RTCPSender::Sending() const {
danilchap56036ff2016-03-22 11:14:09 -0700217 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200218 return sending_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000219}
220
Erik Språng61be2a42015-04-27 13:32:52 +0200221int32_t RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
222 bool sending) {
223 bool sendRTCPBye = false;
224 {
danilchap56036ff2016-03-22 11:14:09 -0700225 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000226
pbosda903ea2015-10-02 02:36:56 -0700227 if (method_ != RtcpMode::kOff) {
Erik Språng242e22b2015-05-11 10:17:43 +0200228 if (sending == false && sending_ == true) {
Erik Språng61be2a42015-04-27 13:32:52 +0200229 // Trigger RTCP bye
230 sendRTCPBye = true;
231 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000232 }
Erik Språng242e22b2015-05-11 10:17:43 +0200233 sending_ = sending;
Erik Språng61be2a42015-04-27 13:32:52 +0200234 }
235 if (sendRTCPBye)
236 return SendRTCP(feedback_state, kRtcpBye);
237 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000238}
239
Erik Språng61be2a42015-04-27 13:32:52 +0200240bool RTCPSender::REMB() const {
danilchap56036ff2016-03-22 11:14:09 -0700241 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200242 return remb_enabled_;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000243}
244
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000245void RTCPSender::SetREMBStatus(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700246 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200247 remb_enabled_ = enable;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000248}
249
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000250void RTCPSender::SetREMBData(uint32_t bitrate,
251 const std::vector<uint32_t>& ssrcs) {
danilchap56036ff2016-03-22 11:14:09 -0700252 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200253 remb_bitrate_ = bitrate;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000254 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000255
Erik Språng242e22b2015-05-11 10:17:43 +0200256 if (remb_enabled_)
257 SetFlag(kRtcpRemb, false);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000258 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
259 // throttled by the caller.
Erik Språng242e22b2015-05-11 10:17:43 +0200260 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000261}
262
Erik Språng61be2a42015-04-27 13:32:52 +0200263bool RTCPSender::TMMBR() const {
danilchap56036ff2016-03-22 11:14:09 -0700264 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200265 return IsFlagPresent(RTCPPacketType::kRtcpTmmbr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000266}
267
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000268void RTCPSender::SetTMMBRStatus(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700269 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200270 if (enable) {
271 SetFlag(RTCPPacketType::kRtcpTmmbr, false);
272 } else {
273 ConsumeFlag(RTCPPacketType::kRtcpTmmbr, true);
274 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000275}
276
nisse284542b2017-01-10 08:58:32 -0800277void RTCPSender::SetMaxRtpPacketSize(size_t max_packet_size) {
nisse6f142eb2017-02-21 07:32:47 -0800278 rtc::CritScope lock(&critical_section_rtcp_sender_);
nisse284542b2017-01-10 08:58:32 -0800279 max_packet_size_ = max_packet_size;
danilchap41befce2016-03-30 11:11:51 -0700280}
281
danilchap71fead22016-08-18 02:01:49 -0700282void RTCPSender::SetTimestampOffset(uint32_t timestamp_offset) {
danilchap56036ff2016-03-22 11:14:09 -0700283 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap71fead22016-08-18 02:01:49 -0700284 timestamp_offset_ = timestamp_offset;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000285}
286
287void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
288 int64_t capture_time_ms) {
danilchap56036ff2016-03-22 11:14:09 -0700289 rtc::CritScope lock(&critical_section_rtcp_sender_);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000290 last_rtp_timestamp_ = rtp_timestamp;
291 if (capture_time_ms < 0) {
292 // We don't currently get a capture time from VoiceEngine.
Erik Språng242e22b2015-05-11 10:17:43 +0200293 last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000294 } else {
295 last_frame_capture_time_ms_ = capture_time_ms;
296 }
297}
298
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000299void RTCPSender::SetSSRC(uint32_t ssrc) {
danilchap56036ff2016-03-22 11:14:09 -0700300 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000301
Erik Språng242e22b2015-05-11 10:17:43 +0200302 if (ssrc_ != 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200303 // not first SetSSRC, probably due to a collision
304 // schedule a new RTCP report
305 // make sure that we send a RTP packet
Erik Språng242e22b2015-05-11 10:17:43 +0200306 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
Erik Språng61be2a42015-04-27 13:32:52 +0200307 }
Erik Språng242e22b2015-05-11 10:17:43 +0200308 ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000309}
310
Erik Språng61be2a42015-04-27 13:32:52 +0200311void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
danilchap56036ff2016-03-22 11:14:09 -0700312 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200313 remote_ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000314}
315
Peter Boström9ba52f82015-06-01 14:12:28 +0200316int32_t RTCPSender::SetCNAME(const char* c_name) {
317 if (!c_name)
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000318 return -1;
319
kwiberg352444f2016-11-28 15:58:53 -0800320 RTC_DCHECK_LT(strlen(c_name), RTCP_CNAME_SIZE);
danilchap56036ff2016-03-22 11:14:09 -0700321 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200322 cname_ = c_name;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000323 return 0;
324}
325
Erik Språng0ea42d32015-06-25 14:46:16 +0200326int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC, const char* c_name) {
danilchap56036ff2016-03-22 11:14:09 -0700327 RTC_DCHECK(c_name);
kwiberg352444f2016-11-28 15:58:53 -0800328 RTC_DCHECK_LT(strlen(c_name), RTCP_CNAME_SIZE);
danilchap56036ff2016-03-22 11:14:09 -0700329 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap74e8df8f2017-03-16 08:04:08 -0700330 // One spot is reserved for ssrc_/cname_.
331 // TODO(danilchap): Add support for more than 30 contributes by sending
332 // several sdes packets.
333 if (csrc_cnames_.size() >= rtcp::Sdes::kMaxNumberOfChunks - 1)
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000334 return -1;
Erik Språng0ea42d32015-06-25 14:46:16 +0200335
336 csrc_cnames_[SSRC] = c_name;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000337 return 0;
338}
339
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000340int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
danilchap56036ff2016-03-22 11:14:09 -0700341 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200342 auto it = csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000343
Erik Språng242e22b2015-05-11 10:17:43 +0200344 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000345 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200346
Erik Språng242e22b2015-05-11 10:17:43 +0200347 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000348 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000349}
350
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000351bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
danilchap162abd32015-12-10 02:39:40 -0800352 /*
353 For audio we use a fix 5 sec interval
niklase@google.com470e71d2011-07-07 08:21:25 +0000354
danilchap162abd32015-12-10 02:39:40 -0800355 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
356 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
357 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000358
359
danilchap162abd32015-12-10 02:39:40 -0800360 From RFC 3550
niklase@google.com470e71d2011-07-07 08:21:25 +0000361
danilchap162abd32015-12-10 02:39:40 -0800362 MAX RTCP BW is 5% if the session BW
363 A send report is approximately 65 bytes inc CNAME
364 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000365
danilchap162abd32015-12-10 02:39:40 -0800366 The RECOMMENDED value for the reduced minimum in seconds is 360
367 divided by the session bandwidth in kilobits/second. This minimum
368 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
niklase@google.com470e71d2011-07-07 08:21:25 +0000369
danilchap162abd32015-12-10 02:39:40 -0800370 If the participant has not yet sent an RTCP packet (the variable
371 initial is true), the constant Tmin is set to 2.5 seconds, else it
372 is set to 5 seconds.
niklase@google.com470e71d2011-07-07 08:21:25 +0000373
danilchap162abd32015-12-10 02:39:40 -0800374 The interval between RTCP packets is varied randomly over the
375 range [0.5,1.5] times the calculated interval to avoid unintended
376 synchronization of all participants
niklase@google.com470e71d2011-07-07 08:21:25 +0000377
danilchap162abd32015-12-10 02:39:40 -0800378 if we send
379 If the participant is a sender (we_sent true), the constant C is
380 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
381 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
382 number of senders.
niklase@google.com470e71d2011-07-07 08:21:25 +0000383
danilchap162abd32015-12-10 02:39:40 -0800384 if we receive only
385 If we_sent is not true, the constant C is set
386 to the average RTCP packet size divided by 75% of the RTCP
387 bandwidth. The constant n is set to the number of receivers
388 (members - senders). If the number of senders is greater than
389 25%, senders and receivers are treated together.
niklase@google.com470e71d2011-07-07 08:21:25 +0000390
danilchap162abd32015-12-10 02:39:40 -0800391 reconsideration NOT required for peer-to-peer
392 "timer reconsideration" is
393 employed. This algorithm implements a simple back-off mechanism
394 which causes users to hold back RTCP packet transmission if the
395 group sizes are increasing.
niklase@google.com470e71d2011-07-07 08:21:25 +0000396
danilchap162abd32015-12-10 02:39:40 -0800397 n = number of members
398 C = avg_size/(rtcpBW/4)
niklase@google.com470e71d2011-07-07 08:21:25 +0000399
danilchap162abd32015-12-10 02:39:40 -0800400 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
niklase@google.com470e71d2011-07-07 08:21:25 +0000401
danilchap162abd32015-12-10 02:39:40 -0800402 4. The calculated interval T is set to a number uniformly distributed
403 between 0.5 and 1.5 times the deterministic calculated interval.
niklase@google.com470e71d2011-07-07 08:21:25 +0000404
danilchap162abd32015-12-10 02:39:40 -0800405 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
406 for the fact that the timer reconsideration algorithm converges to
407 a value of the RTCP bandwidth below the intended average
408 */
niklase@google.com470e71d2011-07-07 08:21:25 +0000409
Erik Språng242e22b2015-05-11 10:17:43 +0200410 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000411
danilchap56036ff2016-03-22 11:14:09 -0700412 rtc::CritScope lock(&critical_section_rtcp_sender_);
xians@webrtc.org8738d272011-11-25 13:43:53 +0000413
pbosda903ea2015-10-02 02:36:56 -0700414 if (method_ == RtcpMode::kOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000415 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000416
Erik Språng242e22b2015-05-11 10:17:43 +0200417 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200418 // for video key-frames we want to send the RTCP before the large key-frame
419 // if we have a 100 ms margin
420 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
421 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000422
Erik Språng242e22b2015-05-11 10:17:43 +0200423 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200424 return true;
425 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200426 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200427 // wrap
428 return true;
429 }
430 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000431}
432
danilchap56036ff2016-03-22 11:14:09 -0700433std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSR(const RtcpContext& ctx) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200434 // Timestamp shouldn't be estimated before first media frame.
435 RTC_DCHECK_GE(last_frame_capture_time_ms_, 0);
Erik Språng61be2a42015-04-27 13:32:52 +0200436 // The timestamp of this RTCP packet should be estimated as the timestamp of
437 // the frame being captured at this moment. We are calculating that
438 // timestamp as the last frame's timestamp + the time since the last frame
439 // was captured.
solenbergb19d2882016-10-03 06:22:25 -0700440 uint32_t rtp_rate =
441 (audio_ ? kBogusRtpRateForAudioRtcp : kVideoPayloadTypeFrequency) / 1000;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200442 uint32_t rtp_timestamp =
danilchap71fead22016-08-18 02:01:49 -0700443 timestamp_offset_ + last_rtp_timestamp_ +
solenbergb19d2882016-10-03 06:22:25 -0700444 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) * rtp_rate;
niklase@google.com470e71d2011-07-07 08:21:25 +0000445
Erik Språngf7c57762015-12-04 10:40:35 +0100446 rtcp::SenderReport* report = new rtcp::SenderReport();
danilchap822a16f2016-09-27 09:27:47 -0700447 report->SetSenderSsrc(ssrc_);
danilchap51813b32016-12-16 02:44:36 -0800448 report->SetNtp(ctx.now_);
danilchap822a16f2016-09-27 09:27:47 -0700449 report->SetRtpTimestamp(rtp_timestamp);
450 report->SetPacketCount(ctx.feedback_state_.packets_sent);
451 report->SetOctetCount(ctx.feedback_state_.media_bytes_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000452
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200453 for (auto it : report_blocks_)
danilchap822a16f2016-09-27 09:27:47 -0700454 report->AddReportBlock(it.second);
niklase@google.com470e71d2011-07-07 08:21:25 +0000455
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200456 report_blocks_.clear();
Erik Språngf7c57762015-12-04 10:40:35 +0100457
danilchap56036ff2016-03-22 11:14:09 -0700458 return std::unique_ptr<rtcp::RtcpPacket>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000459}
460
danilchap56036ff2016-03-22 11:14:09 -0700461std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSDES(
Erik Språngf7c57762015-12-04 10:40:35 +0100462 const RtcpContext& ctx) {
Erik Språng0ea42d32015-06-25 14:46:16 +0200463 size_t length_cname = cname_.length();
kwiberg352444f2016-11-28 15:58:53 -0800464 RTC_CHECK_LT(length_cname, RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000465
Erik Språngf7c57762015-12-04 10:40:35 +0100466 rtcp::Sdes* sdes = new rtcp::Sdes();
danilchap822a16f2016-09-27 09:27:47 -0700467 sdes->AddCName(ssrc_, cname_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200468
danilchap74e8df8f2017-03-16 08:04:08 -0700469 for (const auto& it : csrc_cnames_)
470 RTC_CHECK(sdes->AddCName(it.first, it.second));
Erik Språng0ea42d32015-06-25 14:46:16 +0200471
danilchap56036ff2016-03-22 11:14:09 -0700472 return std::unique_ptr<rtcp::RtcpPacket>(sdes);
niklase@google.com470e71d2011-07-07 08:21:25 +0000473}
474
danilchap56036ff2016-03-22 11:14:09 -0700475std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildRR(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100476 rtcp::ReceiverReport* report = new rtcp::ReceiverReport();
danilchap822a16f2016-09-27 09:27:47 -0700477 report->SetSenderSsrc(ssrc_);
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200478 for (auto it : report_blocks_)
danilchap822a16f2016-09-27 09:27:47 -0700479 report->AddReportBlock(it.second);
Erik Språng61be2a42015-04-27 13:32:52 +0200480
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200481 report_blocks_.clear();
danilchap56036ff2016-03-22 11:14:09 -0700482 return std::unique_ptr<rtcp::RtcpPacket>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000483}
484
danilchap56036ff2016-03-22 11:14:09 -0700485std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildPLI(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100486 rtcp::Pli* pli = new rtcp::Pli();
danilchap822a16f2016-09-27 09:27:47 -0700487 pli->SetSenderSsrc(ssrc_);
488 pli->SetMediaSsrc(remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200489
Erik Språng242e22b2015-05-11 10:17:43 +0200490 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
491 "RTCPSender::PLI");
492 ++packet_type_counter_.pli_packets;
493 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
494 ssrc_, packet_type_counter_.pli_packets);
495
danilchap56036ff2016-03-22 11:14:09 -0700496 return std::unique_ptr<rtcp::RtcpPacket>(pli);
Erik Språng61be2a42015-04-27 13:32:52 +0200497}
498
danilchap56036ff2016-03-22 11:14:09 -0700499std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildFIR(const RtcpContext& ctx) {
danilchap498ee8e2017-02-08 05:24:31 -0800500 ++sequence_number_fir_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000501
Erik Språngf7c57762015-12-04 10:40:35 +0100502 rtcp::Fir* fir = new rtcp::Fir();
danilchap822a16f2016-09-27 09:27:47 -0700503 fir->SetSenderSsrc(ssrc_);
504 fir->AddRequestTo(remote_ssrc_, sequence_number_fir_);
Erik Språng242e22b2015-05-11 10:17:43 +0200505
506 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
507 "RTCPSender::FIR");
508 ++packet_type_counter_.fir_packets;
509 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
510 ssrc_, packet_type_counter_.fir_packets);
511
danilchap56036ff2016-03-22 11:14:09 -0700512 return std::unique_ptr<rtcp::RtcpPacket>(fir);
niklase@google.com470e71d2011-07-07 08:21:25 +0000513}
514
danilchap56036ff2016-03-22 11:14:09 -0700515std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildREMB(
Erik Språngf7c57762015-12-04 10:40:35 +0100516 const RtcpContext& ctx) {
517 rtcp::Remb* remb = new rtcp::Remb();
danilchap822a16f2016-09-27 09:27:47 -0700518 remb->SetSenderSsrc(ssrc_);
519 remb->SetBitrateBps(remb_bitrate_);
520 remb->SetSsrcs(remb_ssrcs_);
Erik Språng61be2a42015-04-27 13:32:52 +0200521
Erik Språng242e22b2015-05-11 10:17:43 +0200522 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
523 "RTCPSender::REMB");
524
danilchap56036ff2016-03-22 11:14:09 -0700525 return std::unique_ptr<rtcp::RtcpPacket>(remb);
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000526}
527
Erik Språng61be2a42015-04-27 13:32:52 +0200528void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
danilchap56036ff2016-03-22 11:14:09 -0700529 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap2b616392016-08-18 06:17:42 -0700530 tmmbr_send_bps_ = target_bitrate;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000531}
532
danilchap56036ff2016-03-22 11:14:09 -0700533std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBR(
Erik Språngf7c57762015-12-04 10:40:35 +0100534 const RtcpContext& ctx) {
535 if (ctx.feedback_state_.module == nullptr)
536 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200537 // Before sending the TMMBR check the received TMMBN, only an owner is
538 // allowed to raise the bitrate:
539 // * If the sender is an owner of the TMMBN -> send TMMBR
540 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000541
Erik Språng61be2a42015-04-27 13:32:52 +0200542 // get current bounding set from RTCP receiver
danilchap2b616392016-08-18 06:17:42 -0700543 bool tmmbr_owner = false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000544
Erik Språng242e22b2015-05-11 10:17:43 +0200545 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
546 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
Erik Språng61be2a42015-04-27 13:32:52 +0200547 // since RTCPreceiver is not doing the reverse we should be fine
danilchap2b616392016-08-18 06:17:42 -0700548 std::vector<rtcp::TmmbItem> candidates =
549 ctx.feedback_state_.module->BoundingSet(&tmmbr_owner);
niklase@google.com470e71d2011-07-07 08:21:25 +0000550
danilchap2b616392016-08-18 06:17:42 -0700551 if (!candidates.empty()) {
552 for (const auto& candidate : candidates) {
553 if (candidate.bitrate_bps() == tmmbr_send_bps_ &&
554 candidate.packet_overhead() == packet_oh_send_) {
Erik Språngf7c57762015-12-04 10:40:35 +0100555 // Do not send the same tuple.
556 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200557 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000558 }
danilchap2b616392016-08-18 06:17:42 -0700559 if (!tmmbr_owner) {
560 // Use received bounding set as candidate set.
561 // Add current tuple.
562 candidates.emplace_back(ssrc_, tmmbr_send_bps_, packet_oh_send_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000563
danilchap2b616392016-08-18 06:17:42 -0700564 // Find bounding set.
danilchap2f69ce92016-08-16 03:21:38 -0700565 std::vector<rtcp::TmmbItem> bounding =
566 TMMBRHelp::FindBoundingSet(std::move(candidates));
danilchap2b616392016-08-18 06:17:42 -0700567 tmmbr_owner = TMMBRHelp::IsOwner(bounding, ssrc_);
568 if (!tmmbr_owner) {
Erik Språngf7c57762015-12-04 10:40:35 +0100569 // Did not enter bounding set, no meaning to send this request.
570 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200571 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000572 }
Erik Språng61be2a42015-04-27 13:32:52 +0200573 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000574
danilchap2b616392016-08-18 06:17:42 -0700575 if (!tmmbr_send_bps_)
Erik Språngf7c57762015-12-04 10:40:35 +0100576 return nullptr;
sprang81a3e602015-08-21 05:30:11 -0700577
Erik Språngf7c57762015-12-04 10:40:35 +0100578 rtcp::Tmmbr* tmmbr = new rtcp::Tmmbr();
danilchap822a16f2016-09-27 09:27:47 -0700579 tmmbr->SetSenderSsrc(ssrc_);
danilchapf174e3a2016-02-05 04:56:36 -0800580 rtcp::TmmbItem request;
581 request.set_ssrc(remote_ssrc_);
danilchap2b616392016-08-18 06:17:42 -0700582 request.set_bitrate_bps(tmmbr_send_bps_);
danilchapf174e3a2016-02-05 04:56:36 -0800583 request.set_packet_overhead(packet_oh_send_);
danilchap822a16f2016-09-27 09:27:47 -0700584 tmmbr->AddTmmbr(request);
Erik Språngf7c57762015-12-04 10:40:35 +0100585
danilchap56036ff2016-03-22 11:14:09 -0700586 return std::unique_ptr<rtcp::RtcpPacket>(tmmbr);
Erik Språng61be2a42015-04-27 13:32:52 +0200587}
588
danilchap56036ff2016-03-22 11:14:09 -0700589std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBN(
Erik Språngf7c57762015-12-04 10:40:35 +0100590 const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100591 rtcp::Tmmbn* tmmbn = new rtcp::Tmmbn();
danilchap822a16f2016-09-27 09:27:47 -0700592 tmmbn->SetSenderSsrc(ssrc_);
danilchap6eaa3a42016-05-09 10:59:50 -0700593 for (const rtcp::TmmbItem& tmmbr : tmmbn_to_send_) {
594 if (tmmbr.bitrate_bps() > 0) {
danilchap822a16f2016-09-27 09:27:47 -0700595 tmmbn->AddTmmbr(tmmbr);
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000596 }
Erik Språng61be2a42015-04-27 13:32:52 +0200597 }
sprangd83df502015-08-27 01:05:08 -0700598
danilchap56036ff2016-03-22 11:14:09 -0700599 return std::unique_ptr<rtcp::RtcpPacket>(tmmbn);
niklase@google.com470e71d2011-07-07 08:21:25 +0000600}
601
danilchap56036ff2016-03-22 11:14:09 -0700602std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildAPP(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100603 rtcp::App* app = new rtcp::App();
danilchap822a16f2016-09-27 09:27:47 -0700604 app->SetSsrc(ssrc_);
605 app->SetSubType(app_sub_type_);
606 app->SetName(app_name_);
607 app->SetData(app_data_.get(), app_length_);
Erik Språng521875a2015-09-01 10:11:16 +0200608
danilchap56036ff2016-03-22 11:14:09 -0700609 return std::unique_ptr<rtcp::RtcpPacket>(app);
Erik Språng61be2a42015-04-27 13:32:52 +0200610}
611
danilchap56036ff2016-03-22 11:14:09 -0700612std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildNACK(
Erik Språngf7c57762015-12-04 10:40:35 +0100613 const RtcpContext& ctx) {
614 rtcp::Nack* nack = new rtcp::Nack();
danilchap822a16f2016-09-27 09:27:47 -0700615 nack->SetSenderSsrc(ssrc_);
616 nack->SetMediaSsrc(remote_ssrc_);
617 nack->SetPacketIds(ctx.nack_list_, ctx.nack_size_);
Erik Språng61be2a42015-04-27 13:32:52 +0200618
619 // Report stats.
620 NACKStringBuilder stringBuilder;
Erik Språngf7c57762015-12-04 10:40:35 +0100621 for (int idx = 0; idx < ctx.nack_size_; ++idx) {
622 stringBuilder.PushNACK(ctx.nack_list_[idx]);
623 nack_stats_.ReportRequest(ctx.nack_list_[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +0200624 }
Erik Språng61be2a42015-04-27 13:32:52 +0200625 packet_type_counter_.nack_requests = nack_stats_.requests();
626 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +0200627
628 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
629 "RTCPSender::NACK", "nacks",
630 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
631 ++packet_type_counter_.nack_packets;
632 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
633 ssrc_, packet_type_counter_.nack_packets);
634
danilchap56036ff2016-03-22 11:14:09 -0700635 return std::unique_ptr<rtcp::RtcpPacket>(nack);
Erik Språng61be2a42015-04-27 13:32:52 +0200636}
637
danilchap56036ff2016-03-22 11:14:09 -0700638std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildBYE(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100639 rtcp::Bye* bye = new rtcp::Bye();
danilchap822a16f2016-09-27 09:27:47 -0700640 bye->SetSenderSsrc(ssrc_);
641 bye->SetCsrcs(csrcs_);
sprangd8ee4f92015-08-24 03:25:19 -0700642
danilchap56036ff2016-03-22 11:14:09 -0700643 return std::unique_ptr<rtcp::RtcpPacket>(bye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000644}
645
sprang5e38c962016-12-01 05:18:09 -0800646std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildExtendedReports(
Erik Språngf7c57762015-12-04 10:40:35 +0100647 const RtcpContext& ctx) {
sprang5e38c962016-12-01 05:18:09 -0800648 std::unique_ptr<rtcp::ExtendedReports> xr(new rtcp::ExtendedReports());
danilchap822a16f2016-09-27 09:27:47 -0700649 xr->SetSenderSsrc(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000650
sprang5e38c962016-12-01 05:18:09 -0800651 if (!sending_ && xr_send_receiver_reference_time_enabled_) {
652 rtcp::Rrtr rrtr;
danilchap51813b32016-12-16 02:44:36 -0800653 rrtr.SetNtp(ctx.now_);
sprang5e38c962016-12-01 05:18:09 -0800654 xr->SetRrtr(rrtr);
655 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000656
sprang5e38c962016-12-01 05:18:09 -0800657 if (ctx.feedback_state_.has_last_xr_rr) {
658 xr->AddDlrrItem(ctx.feedback_state_.last_xr_rr);
659 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000660
sprang5e38c962016-12-01 05:18:09 -0800661 if (video_bitrate_allocation_) {
662 rtcp::TargetBitrate target_bitrate;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000663
sprang5e38c962016-12-01 05:18:09 -0800664 for (int sl = 0; sl < kMaxSpatialLayers; ++sl) {
665 for (int tl = 0; tl < kMaxTemporalStreams; ++tl) {
666 uint32_t layer_bitrate_bps =
667 video_bitrate_allocation_->GetBitrate(sl, tl);
668 if (layer_bitrate_bps > 0)
669 target_bitrate.AddTargetBitrate(sl, tl, layer_bitrate_bps / 1000);
670 }
671 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000672
sprang5e38c962016-12-01 05:18:09 -0800673 xr->SetTargetBitrate(target_bitrate);
674 video_bitrate_allocation_.reset();
675 }
Erik Språngca28fdc2015-08-31 14:00:50 +0200676
sprang5e38c962016-12-01 05:18:09 -0800677 if (xr_voip_metric_) {
678 rtcp::VoipMetric voip;
679 voip.SetMediaSsrc(remote_ssrc_);
680 voip.SetVoipMetric(*xr_voip_metric_);
681 xr_voip_metric_.reset();
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000682
sprang5e38c962016-12-01 05:18:09 -0800683 xr->SetVoipMetric(voip);
684 }
Erik Språngca28fdc2015-08-31 14:00:50 +0200685
sprang5e38c962016-12-01 05:18:09 -0800686 return std::move(xr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000687}
688
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000689int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200690 RTCPPacketType packetType,
691 int32_t nack_size,
nissecd386eb2017-03-14 08:54:43 -0700692 const uint16_t* nack_list) {
Erik Språng242e22b2015-05-11 10:17:43 +0200693 return SendCompoundRTCP(
694 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
nissecd386eb2017-03-14 08:54:43 -0700695 nack_size, nack_list);
Erik Språng242e22b2015-05-11 10:17:43 +0200696}
697
698int32_t RTCPSender::SendCompoundRTCP(
699 const FeedbackState& feedback_state,
Erik Språngf7c57762015-12-04 10:40:35 +0100700 const std::set<RTCPPacketType>& packet_types,
Erik Språng242e22b2015-05-11 10:17:43 +0200701 int32_t nack_size,
nissecd386eb2017-03-14 08:54:43 -0700702 const uint16_t* nack_list) {
terelius429c3452016-01-21 05:42:04 -0800703 PacketContainer container(transport_, event_log_);
nisse6f142eb2017-02-21 07:32:47 -0800704 size_t max_packet_size;
705
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000706 {
danilchap56036ff2016-03-22 11:14:09 -0700707 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbosda903ea2015-10-02 02:36:56 -0700708 if (method_ == RtcpMode::kOff) {
Erik Språng61be2a42015-04-27 13:32:52 +0200709 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
710 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +0000711 }
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200712 // Add all flags as volatile. Non volatile entries will not be overwritten.
713 // All new volatile flags added will be consumed by the end of this call.
714 SetFlags(packet_types, true);
715
716 // Prevent sending streams to send SR before any media has been sent.
717 const bool can_calculate_rtp_timestamp = (last_frame_capture_time_ms_ >= 0);
718 if (!can_calculate_rtp_timestamp) {
719 bool consumed_sr_flag = ConsumeFlag(kRtcpSr);
720 bool consumed_report_flag = sending_ && ConsumeFlag(kRtcpReport);
721 bool sender_report = consumed_report_flag || consumed_sr_flag;
722 if (sender_report && AllVolatileFlagsConsumed()) {
723 // This call was for Sender Report and nothing else.
724 return 0;
725 }
726 if (sending_ && method_ == RtcpMode::kCompound) {
727 // Not allowed to send any RTCP packet without sender report.
728 return -1;
729 }
730 }
731
732 if (packet_type_counter_.first_packet_time_ms == -1)
733 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språngf7c57762015-12-04 10:40:35 +0100734
735 // We need to send our NTP even if we haven't received any reports.
nissecd386eb2017-03-14 08:54:43 -0700736 RtcpContext context(feedback_state, nack_size, nack_list,
danilchap37953762017-02-09 11:15:25 -0800737 clock_->CurrentNtpTime());
Erik Språngf7c57762015-12-04 10:40:35 +0100738
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200739 PrepareReport(feedback_state);
Erik Språngf7c57762015-12-04 10:40:35 +0100740
danilchap56036ff2016-03-22 11:14:09 -0700741 std::unique_ptr<rtcp::RtcpPacket> packet_bye;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800742
Erik Språngf7c57762015-12-04 10:40:35 +0100743 auto it = report_flags_.begin();
744 while (it != report_flags_.end()) {
745 auto builder_it = builders_.find(it->type);
sprang5e38c962016-12-01 05:18:09 -0800746 RTC_DCHECK(builder_it != builders_.end())
747 << "Could not find builder for packet type " << it->type;
Erik Språngf7c57762015-12-04 10:40:35 +0100748 if (it->is_volatile) {
749 report_flags_.erase(it++);
750 } else {
751 ++it;
752 }
753
754 BuilderFunc func = builder_it->second;
danilchap56036ff2016-03-22 11:14:09 -0700755 std::unique_ptr<rtcp::RtcpPacket> packet = (this->*func)(context);
Erik Språngf7c57762015-12-04 10:40:35 +0100756 if (packet.get() == nullptr)
757 return -1;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800758 // If there is a BYE, don't append now - save it and append it
759 // at the end later.
760 if (builder_it->first == kRtcpBye) {
761 packet_bye = std::move(packet);
762 } else {
763 container.Append(packet.release());
764 }
765 }
766
767 // Append the BYE now at the end
768 if (packet_bye) {
769 container.Append(packet_bye.release());
Erik Språngf7c57762015-12-04 10:40:35 +0100770 }
771
772 if (packet_type_counter_observer_ != nullptr) {
773 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
774 remote_ssrc_, packet_type_counter_);
775 }
776
777 RTC_DCHECK(AllVolatileFlagsConsumed());
nisse6f142eb2017-02-21 07:32:47 -0800778 max_packet_size = max_packet_size_;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000779 }
Erik Språng61be2a42015-04-27 13:32:52 +0200780
nisse6f142eb2017-02-21 07:32:47 -0800781 size_t bytes_sent = container.SendPackets(max_packet_size);
Erik Språngf7c57762015-12-04 10:40:35 +0100782 return bytes_sent == 0 ? -1 : 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000783}
784
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200785void RTCPSender::PrepareReport(const FeedbackState& feedback_state) {
Erik Språng242e22b2015-05-11 10:17:43 +0200786 bool generate_report;
787 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
788 // Report type already explicitly set, don't automatically populate.
789 generate_report = true;
henrikg91d6ede2015-09-17 00:24:34 -0700790 RTC_DCHECK(ConsumeFlag(kRtcpReport) == false);
Erik Språng242e22b2015-05-11 10:17:43 +0200791 } else {
792 generate_report =
pbosda903ea2015-10-02 02:36:56 -0700793 (ConsumeFlag(kRtcpReport) && method_ == RtcpMode::kReducedSize) ||
794 method_ == RtcpMode::kCompound;
Erik Språng242e22b2015-05-11 10:17:43 +0200795 if (generate_report)
796 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000797 }
798
Erik Språng0ea42d32015-06-25 14:46:16 +0200799 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
Erik Språng242e22b2015-05-11 10:17:43 +0200800 SetFlag(kRtcpSdes, true);
801
Erik Språng242e22b2015-05-11 10:17:43 +0200802 if (generate_report) {
sprang5e38c962016-12-01 05:18:09 -0800803 if ((!sending_ && xr_send_receiver_reference_time_enabled_) ||
804 feedback_state.has_last_xr_rr || video_bitrate_allocation_) {
805 SetFlag(kRtcpAnyExtendedReports, true);
806 }
Erik Språng242e22b2015-05-11 10:17:43 +0200807
808 // generate next time to send an RTCP report
danilchap47a740b2015-12-15 00:30:07 -0800809 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000810
danilchap47a740b2015-12-15 00:30:07 -0800811 if (!audio_) {
Erik Språng242e22b2015-05-11 10:17:43 +0200812 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200813 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
814 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
815 if (send_bitrate_kbit != 0)
816 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000817 }
Erik Språng61be2a42015-04-27 13:32:52 +0200818 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
819 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
Erik Språng61be2a42015-04-27 13:32:52 +0200820 }
danilchap47a740b2015-12-15 00:30:07 -0800821 // The interval between RTCP packets is varied randomly over the
822 // range [1/2,3/2] times the calculated interval.
823 uint32_t timeToNext =
824 random_.Rand(minIntervalMs * 1 / 2, minIntervalMs * 3 / 2);
Erik Språng242e22b2015-05-11 10:17:43 +0200825 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000826
Per83d09102016-04-15 14:59:13 +0200827 if (receive_statistics_) {
828 StatisticianMap statisticians =
829 receive_statistics_->GetActiveStatisticians();
830 RTC_DCHECK(report_blocks_.empty());
831 for (auto& it : statisticians) {
832 AddReportBlock(feedback_state, it.first, it.second);
833 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000834 }
835 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000836}
837
danilchapa72e7342015-12-22 08:07:45 -0800838bool RTCPSender::AddReportBlock(const FeedbackState& feedback_state,
839 uint32_t ssrc,
840 StreamStatistician* statistician) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000841 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000842 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000843 if (!statistician->GetStatistics(&stats, true))
844 return false;
danilchapa72e7342015-12-22 08:07:45 -0800845
846 if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) {
847 LOG(LS_WARNING) << "Too many report blocks.";
848 return false;
849 }
850 RTC_DCHECK(report_blocks_.find(ssrc) == report_blocks_.end());
851 rtcp::ReportBlock* block = &report_blocks_[ssrc];
danilchap822a16f2016-09-27 09:27:47 -0700852 block->SetMediaSsrc(ssrc);
853 block->SetFractionLost(stats.fraction_lost);
854 if (!block->SetCumulativeLost(stats.cumulative_lost)) {
danilchapa72e7342015-12-22 08:07:45 -0800855 report_blocks_.erase(ssrc);
856 LOG(LS_WARNING) << "Cumulative lost is oversized.";
857 return false;
858 }
danilchap822a16f2016-09-27 09:27:47 -0700859 block->SetExtHighestSeqNum(stats.extended_max_sequence_number);
860 block->SetJitter(stats.jitter);
861 block->SetLastSr(feedback_state.remote_sr);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000862
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200863 // TODO(sprang): Do we really need separate time stamps for each report?
864 // Get our NTP as late as possible to avoid a race.
danilchap42287842017-02-20 06:40:18 -0800865 NtpTime ntp = clock_->CurrentNtpTime();
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000866
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200867 // Delay since last received report.
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000868 if ((feedback_state.last_rr_ntp_secs != 0) ||
869 (feedback_state.last_rr_ntp_frac != 0)) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200870 // Get the 16 lowest bits of seconds and the 16 highest bits of fractions.
danilchap42287842017-02-20 06:40:18 -0800871 uint32_t now = CompactNtp(ntp);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000872
Erik Språng61be2a42015-04-27 13:32:52 +0200873 uint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
874 receiveTime <<= 16;
875 receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000876
danilchap822a16f2016-09-27 09:27:47 -0700877 block->SetDelayLastSr(now - receiveTime);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000878 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000879 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000880}
881
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000882void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
kwiberg352444f2016-11-28 15:58:53 -0800883 RTC_DCHECK_LE(csrcs.size(), kRtpCsrcSize);
danilchap56036ff2016-03-22 11:14:09 -0700884 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000885 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +0000886}
887
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000888int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
889 uint32_t name,
890 const uint8_t* data,
891 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +0200892 if (length % 4 != 0) {
893 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
894 return -1;
895 }
danilchap56036ff2016-03-22 11:14:09 -0700896 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000897
Erik Språng242e22b2015-05-11 10:17:43 +0200898 SetFlag(kRtcpApp, true);
899 app_sub_type_ = subType;
900 app_name_ = name;
901 app_data_.reset(new uint8_t[length]);
902 app_length_ = length;
903 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +0200904 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000905}
906
spranga790d832016-12-02 07:29:44 -0800907// TODO(sprang): Remove support for VoIP metrics? (Not used in receiver.)
Erik Språng61be2a42015-04-27 13:32:52 +0200908int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
danilchap56036ff2016-03-22 11:14:09 -0700909 rtc::CritScope lock(&critical_section_rtcp_sender_);
sprang5e38c962016-12-01 05:18:09 -0800910 xr_voip_metric_.emplace(*VoIPMetric);
niklase@google.com470e71d2011-07-07 08:21:25 +0000911
sprang5e38c962016-12-01 05:18:09 -0800912 SetFlag(kRtcpAnyExtendedReports, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200913 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000914}
915
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000916void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700917 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200918 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000919}
920
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000921bool RTCPSender::RtcpXrReceiverReferenceTime() const {
danilchap56036ff2016-03-22 11:14:09 -0700922 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200923 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000924}
925
danilchap853ecb22016-08-22 08:26:15 -0700926void RTCPSender::SetTmmbn(std::vector<rtcp::TmmbItem> bounding_set) {
danilchap56036ff2016-03-22 11:14:09 -0700927 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap853ecb22016-08-22 08:26:15 -0700928 tmmbn_to_send_ = std::move(bounding_set);
danilchap6eaa3a42016-05-09 10:59:50 -0700929 SetFlag(kRtcpTmmbn, true);
niklase@google.com470e71d2011-07-07 08:21:25 +0000930}
Erik Språng61be2a42015-04-27 13:32:52 +0200931
sprang5e38c962016-12-01 05:18:09 -0800932void RTCPSender::SetFlag(uint32_t type, bool is_volatile) {
933 if (type & kRtcpAnyExtendedReports) {
934 report_flags_.insert(ReportFlag(kRtcpAnyExtendedReports, is_volatile));
935 } else {
936 report_flags_.insert(ReportFlag(type, is_volatile));
937 }
Erik Språng242e22b2015-05-11 10:17:43 +0200938}
939
940void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
941 bool is_volatile) {
942 for (RTCPPacketType type : types)
943 SetFlag(type, is_volatile);
944}
945
sprang5e38c962016-12-01 05:18:09 -0800946bool RTCPSender::IsFlagPresent(uint32_t type) const {
Erik Språng242e22b2015-05-11 10:17:43 +0200947 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
948}
949
sprang5e38c962016-12-01 05:18:09 -0800950bool RTCPSender::ConsumeFlag(uint32_t type, bool forced) {
Erik Språng242e22b2015-05-11 10:17:43 +0200951 auto it = report_flags_.find(ReportFlag(type, false));
952 if (it == report_flags_.end())
953 return false;
954 if (it->is_volatile || forced)
955 report_flags_.erase((it));
956 return true;
957}
958
959bool RTCPSender::AllVolatileFlagsConsumed() const {
960 for (const ReportFlag& flag : report_flags_) {
961 if (flag.is_volatile)
962 return false;
963 }
964 return true;
965}
966
sprang5e38c962016-12-01 05:18:09 -0800967void RTCPSender::SetVideoBitrateAllocation(const BitrateAllocation& bitrate) {
968 rtc::CritScope lock(&critical_section_rtcp_sender_);
969 video_bitrate_allocation_.emplace(bitrate);
970 SetFlag(kRtcpAnyExtendedReports, true);
971}
972
sprang233bd872015-09-08 13:25:16 -0700973bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
sprang233bd872015-09-08 13:25:16 -0700974 class Sender : public rtcp::RtcpPacket::PacketReadyCallback {
975 public:
terelius429c3452016-01-21 05:42:04 -0800976 Sender(Transport* transport, RtcEventLog* event_log)
977 : transport_(transport), event_log_(event_log), send_failure_(false) {}
sprang233bd872015-09-08 13:25:16 -0700978
979 void OnPacketReady(uint8_t* data, size_t length) override {
terelius429c3452016-01-21 05:42:04 -0800980 if (transport_->SendRtcp(data, length)) {
981 if (event_log_) {
982 event_log_->LogRtcpPacket(kOutgoingPacket, MediaType::ANY, data,
983 length);
984 }
985 } else {
sprang233bd872015-09-08 13:25:16 -0700986 send_failure_ = true;
terelius429c3452016-01-21 05:42:04 -0800987 }
sprang233bd872015-09-08 13:25:16 -0700988 }
989
990 Transport* const transport_;
terelius429c3452016-01-21 05:42:04 -0800991 RtcEventLog* const event_log_;
sprang233bd872015-09-08 13:25:16 -0700992 bool send_failure_;
terelius429c3452016-01-21 05:42:04 -0800993 // TODO(terelius): We would like to
994 // RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(Sender);
995 // but we can't because of an incorrect warning (C4822) in MVS 2013.
996 } sender(transport_, event_log_);
sprang233bd872015-09-08 13:25:16 -0700997
nisse6f142eb2017-02-21 07:32:47 -0800998 size_t max_packet_size;
stefanb77c7162017-02-06 06:29:38 -0800999 {
1000 rtc::CritScope lock(&critical_section_rtcp_sender_);
1001 if (method_ == RtcpMode::kOff)
1002 return false;
nisse6f142eb2017-02-21 07:32:47 -08001003 max_packet_size = max_packet_size_;
stefanb77c7162017-02-06 06:29:38 -08001004 }
1005
nisse6f142eb2017-02-21 07:32:47 -08001006 RTC_DCHECK_LE(max_packet_size, IP_PACKET_SIZE);
sprang233bd872015-09-08 13:25:16 -07001007 uint8_t buffer[IP_PACKET_SIZE];
nisse6f142eb2017-02-21 07:32:47 -08001008 return packet.BuildExternalBuffer(buffer, max_packet_size, &sender) &&
sprang233bd872015-09-08 13:25:16 -07001009 !sender.send_failure_;
1010}
1011
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001012} // namespace webrtc