blob: 986d51acd40702c9c25ced0786ca38b60c44c375 [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 Chapovalov2c132972016-01-15 15:21:21 +010033#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rpsi.h"
Danil Chapovalov1567d0b2016-01-15 17:34:27 +010034#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sdes.h"
danilchap34ed2b92016-01-18 02:43:32 -080035#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sender_report.h"
danilchap92e677a2016-01-12 10:04:52 -080036#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sli.h"
danilchapef3d8052016-01-11 03:31:08 -080037#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbn.h"
danilchap7e8145f2016-01-11 11:49:19 -080038#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbr.h"
sprang233bd872015-09-08 13:25:16 -070039#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
tommie4f96502015-10-20 23:00:48 -070040#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
danilchap42287842017-02-20 06:40:18 -080041#include "webrtc/modules/rtp_rtcp/source/time_util.h"
danilchap13deaad2016-05-24 13:25:27 -070042#include "webrtc/modules/rtp_rtcp/source/tmmbr_help.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000043
niklase@google.com470e71d2011-07-07 08:21:25 +000044namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000045
sprang5e38c962016-12-01 05:18:09 -080046namespace {
47const uint32_t kRtcpAnyExtendedReports =
48 kRtcpXrVoipMetric | kRtcpXrReceiverReferenceTime | kRtcpXrDlrrReportBlock |
49 kRtcpXrTargetBitrate;
50} // namespace
51
Erik Språng61be2a42015-04-27 13:32:52 +020052NACKStringBuilder::NACKStringBuilder()
danilchap162abd32015-12-10 02:39:40 -080053 : stream_(""), count_(0), prevNack_(0), consecutive_(false) {}
edjee@google.com79b02892013-04-04 19:43:34 +000054
pbos@webrtc.orgf3e4cee2013-07-31 15:17:19 +000055NACKStringBuilder::~NACKStringBuilder() {}
56
danilchap162abd32015-12-10 02:39:40 -080057void NACKStringBuilder::PushNACK(uint16_t nack) {
Erik Språng242e22b2015-05-11 10:17:43 +020058 if (count_ == 0) {
59 stream_ << nack;
60 } else if (nack == prevNack_ + 1) {
61 consecutive_ = true;
Erik Språng61be2a42015-04-27 13:32:52 +020062 } else {
Erik Språng242e22b2015-05-11 10:17:43 +020063 if (consecutive_) {
64 stream_ << "-" << prevNack_;
65 consecutive_ = false;
edjee@google.com79b02892013-04-04 19:43:34 +000066 }
Erik Språng242e22b2015-05-11 10:17:43 +020067 stream_ << "," << nack;
Erik Språng61be2a42015-04-27 13:32:52 +020068 }
Erik Språng242e22b2015-05-11 10:17:43 +020069 count_++;
70 prevNack_ = nack;
edjee@google.com79b02892013-04-04 19:43:34 +000071}
72
Erik Språng61be2a42015-04-27 13:32:52 +020073std::string NACKStringBuilder::GetResult() {
Erik Språng242e22b2015-05-11 10:17:43 +020074 if (consecutive_) {
75 stream_ << "-" << prevNack_;
76 consecutive_ = false;
Erik Språng61be2a42015-04-27 13:32:52 +020077 }
Erik Språng242e22b2015-05-11 10:17:43 +020078 return stream_.str();
edjee@google.com79b02892013-04-04 19:43:34 +000079}
80
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000081RTCPSender::FeedbackState::FeedbackState()
82 : send_payload_type(0),
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +000083 packets_sent(0),
84 media_bytes_sent(0),
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000085 send_bitrate(0),
86 last_rr_ntp_secs(0),
87 last_rr_ntp_frac(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000088 remote_sr(0),
Erik Språng61be2a42015-04-27 13:32:52 +020089 has_last_xr_rr(false),
danilchap162abd32015-12-10 02:39:40 -080090 module(nullptr) {}
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000091
danilchap2f7dea12016-01-13 02:03:04 -080092class PacketContainer : public rtcp::CompoundPacket,
Erik Språngf7c57762015-12-04 10:40:35 +010093 public rtcp::RtcpPacket::PacketReadyCallback {
94 public:
terelius429c3452016-01-21 05:42:04 -080095 PacketContainer(Transport* transport, RtcEventLog* event_log)
96 : transport_(transport), event_log_(event_log), bytes_sent_(0) {}
Erik Språngf7c57762015-12-04 10:40:35 +010097 virtual ~PacketContainer() {
98 for (RtcpPacket* packet : appended_packets_)
99 delete packet;
100 }
101
102 void OnPacketReady(uint8_t* data, size_t length) override {
terelius429c3452016-01-21 05:42:04 -0800103 if (transport_->SendRtcp(data, length)) {
Erik Språngf7c57762015-12-04 10:40:35 +0100104 bytes_sent_ += length;
terelius429c3452016-01-21 05:42:04 -0800105 if (event_log_) {
106 event_log_->LogRtcpPacket(kOutgoingPacket, MediaType::ANY, data,
107 length);
108 }
109 }
Erik Språngf7c57762015-12-04 10:40:35 +0100110 }
111
danilchap41befce2016-03-30 11:11:51 -0700112 size_t SendPackets(size_t max_payload_length) {
kwiberg352444f2016-11-28 15:58:53 -0800113 RTC_DCHECK_LE(max_payload_length, IP_PACKET_SIZE);
danilchap41befce2016-03-30 11:11:51 -0700114 uint8_t buffer[IP_PACKET_SIZE];
115 BuildExternalBuffer(buffer, max_payload_length, this);
Erik Språngf7c57762015-12-04 10:40:35 +0100116 return bytes_sent_;
117 }
118
119 private:
120 Transport* transport_;
terelius429c3452016-01-21 05:42:04 -0800121 RtcEventLog* const event_log_;
Erik Språngf7c57762015-12-04 10:40:35 +0100122 size_t bytes_sent_;
terelius429c3452016-01-21 05:42:04 -0800123
124 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(PacketContainer);
Erik Språngf7c57762015-12-04 10:40:35 +0100125};
126
127class RTCPSender::RtcpContext {
128 public:
Erik Språng242e22b2015-05-11 10:17:43 +0200129 RtcpContext(const FeedbackState& feedback_state,
130 int32_t nack_size,
131 const uint16_t* nack_list,
Erik Språng242e22b2015-05-11 10:17:43 +0200132 uint64_t picture_id,
danilchap51813b32016-12-16 02:44:36 -0800133 NtpTime now)
Erik Språngf7c57762015-12-04 10:40:35 +0100134 : feedback_state_(feedback_state),
135 nack_size_(nack_size),
136 nack_list_(nack_list),
Erik Språngf7c57762015-12-04 10:40:35 +0100137 picture_id_(picture_id),
danilchap51813b32016-12-16 02:44:36 -0800138 now_(now) {}
Erik Språng242e22b2015-05-11 10:17:43 +0200139
Erik Språngf7c57762015-12-04 10:40:35 +0100140 const FeedbackState& feedback_state_;
141 const int32_t nack_size_;
142 const uint16_t* nack_list_;
Erik Språngf7c57762015-12-04 10:40:35 +0100143 const uint64_t picture_id_;
danilchap51813b32016-12-16 02:44:36 -0800144 const NtpTime now_;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200145};
146
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000147RTCPSender::RTCPSender(
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000148 bool audio,
149 Clock* clock,
150 ReceiveStatistics* receive_statistics,
sprang86fd9ed2015-09-29 04:45:43 -0700151 RtcpPacketTypeCounterObserver* packet_type_counter_observer,
terelius429c3452016-01-21 05:42:04 -0800152 RtcEventLog* event_log,
sprang86fd9ed2015-09-29 04:45:43 -0700153 Transport* outgoing_transport)
Peter Boströmac547a62015-09-17 23:03:57 +0200154 : audio_(audio),
Erik Språng242e22b2015-05-11 10:17:43 +0200155 clock_(clock),
danilchap47a740b2015-12-15 00:30:07 -0800156 random_(clock_->TimeInMicroseconds()),
pbosda903ea2015-10-02 02:36:56 -0700157 method_(RtcpMode::kOff),
terelius429c3452016-01-21 05:42:04 -0800158 event_log_(event_log),
sprang86fd9ed2015-09-29 04:45:43 -0700159 transport_(outgoing_transport),
Erik Språng242e22b2015-05-11 10:17:43 +0200160 using_nack_(false),
161 sending_(false),
162 remb_enabled_(false),
Erik Språng242e22b2015-05-11 10:17:43 +0200163 next_time_to_send_rtcp_(0),
danilchap71fead22016-08-18 02:01:49 -0700164 timestamp_offset_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000165 last_rtp_timestamp_(0),
166 last_frame_capture_time_ms_(-1),
Erik Språng242e22b2015-05-11 10:17:43 +0200167 ssrc_(0),
168 remote_ssrc_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000169 receive_statistics_(receive_statistics),
niklase@google.com470e71d2011-07-07 08:21:25 +0000170
Erik Språng242e22b2015-05-11 10:17:43 +0200171 sequence_number_fir_(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000172
Erik Språng242e22b2015-05-11 10:17:43 +0200173 remb_bitrate_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000174
danilchap2b616392016-08-18 06:17:42 -0700175 tmmbr_send_bps_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200176 packet_oh_send_(0),
nisse284542b2017-01-10 08:58:32 -0800177 max_packet_size_(IP_PACKET_SIZE - 28), // IPv4 + UDP by default.
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000178
Erik Språng242e22b2015-05-11 10:17:43 +0200179 app_sub_type_(0),
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200180 app_name_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200181 app_data_(nullptr),
182 app_length_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000183
Erik Språng242e22b2015-05-11 10:17:43 +0200184 xr_send_receiver_reference_time_enabled_(false),
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000185 packet_type_counter_observer_(packet_type_counter_observer) {
sprang86fd9ed2015-09-29 04:45:43 -0700186 RTC_DCHECK(transport_ != nullptr);
Erik Språng242e22b2015-05-11 10:17:43 +0200187
188 builders_[kRtcpSr] = &RTCPSender::BuildSR;
189 builders_[kRtcpRr] = &RTCPSender::BuildRR;
Erik Språng0ea42d32015-06-25 14:46:16 +0200190 builders_[kRtcpSdes] = &RTCPSender::BuildSDES;
Erik Språng242e22b2015-05-11 10:17:43 +0200191 builders_[kRtcpPli] = &RTCPSender::BuildPLI;
192 builders_[kRtcpFir] = &RTCPSender::BuildFIR;
193 builders_[kRtcpSli] = &RTCPSender::BuildSLI;
194 builders_[kRtcpRpsi] = &RTCPSender::BuildRPSI;
195 builders_[kRtcpRemb] = &RTCPSender::BuildREMB;
196 builders_[kRtcpBye] = &RTCPSender::BuildBYE;
197 builders_[kRtcpApp] = &RTCPSender::BuildAPP;
198 builders_[kRtcpTmmbr] = &RTCPSender::BuildTMMBR;
199 builders_[kRtcpTmmbn] = &RTCPSender::BuildTMMBN;
200 builders_[kRtcpNack] = &RTCPSender::BuildNACK;
sprang5e38c962016-12-01 05:18:09 -0800201 builders_[kRtcpAnyExtendedReports] = &RTCPSender::BuildExtendedReports;
niklase@google.com470e71d2011-07-07 08:21:25 +0000202}
203
danilchap162abd32015-12-10 02:39:40 -0800204RTCPSender::~RTCPSender() {}
niklase@google.com470e71d2011-07-07 08:21:25 +0000205
pbosda903ea2015-10-02 02:36:56 -0700206RtcpMode RTCPSender::Status() const {
danilchap56036ff2016-03-22 11:14:09 -0700207 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200208 return method_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000209}
210
skvlad1c392cc2016-04-01 14:46:44 -0700211void RTCPSender::SetRTCPStatus(RtcpMode new_method) {
danilchap56036ff2016-03-22 11:14:09 -0700212 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000213
skvlad1c392cc2016-04-01 14:46:44 -0700214 if (method_ == RtcpMode::kOff && new_method != RtcpMode::kOff) {
215 // When switching on, reschedule the next packet
216 next_time_to_send_rtcp_ =
Erik Språng242e22b2015-05-11 10:17:43 +0200217 clock_->TimeInMilliseconds() +
218 (audio_ ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
skvlad1c392cc2016-04-01 14:46:44 -0700219 }
220 method_ = new_method;
niklase@google.com470e71d2011-07-07 08:21:25 +0000221}
222
Erik Språng61be2a42015-04-27 13:32:52 +0200223bool RTCPSender::Sending() const {
danilchap56036ff2016-03-22 11:14:09 -0700224 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200225 return sending_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000226}
227
Erik Språng61be2a42015-04-27 13:32:52 +0200228int32_t RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
229 bool sending) {
230 bool sendRTCPBye = false;
231 {
danilchap56036ff2016-03-22 11:14:09 -0700232 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000233
pbosda903ea2015-10-02 02:36:56 -0700234 if (method_ != RtcpMode::kOff) {
Erik Språng242e22b2015-05-11 10:17:43 +0200235 if (sending == false && sending_ == true) {
Erik Språng61be2a42015-04-27 13:32:52 +0200236 // Trigger RTCP bye
237 sendRTCPBye = true;
238 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000239 }
Erik Språng242e22b2015-05-11 10:17:43 +0200240 sending_ = sending;
Erik Språng61be2a42015-04-27 13:32:52 +0200241 }
242 if (sendRTCPBye)
243 return SendRTCP(feedback_state, kRtcpBye);
244 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000245}
246
Erik Språng61be2a42015-04-27 13:32:52 +0200247bool RTCPSender::REMB() const {
danilchap56036ff2016-03-22 11:14:09 -0700248 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200249 return remb_enabled_;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000250}
251
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000252void RTCPSender::SetREMBStatus(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700253 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200254 remb_enabled_ = enable;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000255}
256
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000257void RTCPSender::SetREMBData(uint32_t bitrate,
258 const std::vector<uint32_t>& ssrcs) {
danilchap56036ff2016-03-22 11:14:09 -0700259 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200260 remb_bitrate_ = bitrate;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000261 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000262
Erik Språng242e22b2015-05-11 10:17:43 +0200263 if (remb_enabled_)
264 SetFlag(kRtcpRemb, false);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000265 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
266 // throttled by the caller.
Erik Språng242e22b2015-05-11 10:17:43 +0200267 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000268}
269
Erik Språng61be2a42015-04-27 13:32:52 +0200270bool RTCPSender::TMMBR() const {
danilchap56036ff2016-03-22 11:14:09 -0700271 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200272 return IsFlagPresent(RTCPPacketType::kRtcpTmmbr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000273}
274
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000275void RTCPSender::SetTMMBRStatus(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700276 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200277 if (enable) {
278 SetFlag(RTCPPacketType::kRtcpTmmbr, false);
279 } else {
280 ConsumeFlag(RTCPPacketType::kRtcpTmmbr, true);
281 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000282}
283
nisse284542b2017-01-10 08:58:32 -0800284void RTCPSender::SetMaxRtpPacketSize(size_t max_packet_size) {
nisse6f142eb2017-02-21 07:32:47 -0800285 rtc::CritScope lock(&critical_section_rtcp_sender_);
nisse284542b2017-01-10 08:58:32 -0800286 max_packet_size_ = max_packet_size;
danilchap41befce2016-03-30 11:11:51 -0700287}
288
danilchap71fead22016-08-18 02:01:49 -0700289void RTCPSender::SetTimestampOffset(uint32_t timestamp_offset) {
danilchap56036ff2016-03-22 11:14:09 -0700290 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap71fead22016-08-18 02:01:49 -0700291 timestamp_offset_ = timestamp_offset;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000292}
293
294void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
295 int64_t capture_time_ms) {
danilchap56036ff2016-03-22 11:14:09 -0700296 rtc::CritScope lock(&critical_section_rtcp_sender_);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000297 last_rtp_timestamp_ = rtp_timestamp;
298 if (capture_time_ms < 0) {
299 // We don't currently get a capture time from VoiceEngine.
Erik Språng242e22b2015-05-11 10:17:43 +0200300 last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000301 } else {
302 last_frame_capture_time_ms_ = capture_time_ms;
303 }
304}
305
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000306void RTCPSender::SetSSRC(uint32_t ssrc) {
danilchap56036ff2016-03-22 11:14:09 -0700307 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000308
Erik Språng242e22b2015-05-11 10:17:43 +0200309 if (ssrc_ != 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200310 // not first SetSSRC, probably due to a collision
311 // schedule a new RTCP report
312 // make sure that we send a RTP packet
Erik Språng242e22b2015-05-11 10:17:43 +0200313 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
Erik Språng61be2a42015-04-27 13:32:52 +0200314 }
Erik Språng242e22b2015-05-11 10:17:43 +0200315 ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000316}
317
Erik Språng61be2a42015-04-27 13:32:52 +0200318void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
danilchap56036ff2016-03-22 11:14:09 -0700319 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200320 remote_ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000321}
322
Peter Boström9ba52f82015-06-01 14:12:28 +0200323int32_t RTCPSender::SetCNAME(const char* c_name) {
324 if (!c_name)
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000325 return -1;
326
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_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200329 cname_ = c_name;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000330 return 0;
331}
332
Erik Språng0ea42d32015-06-25 14:46:16 +0200333int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC, const char* c_name) {
danilchap56036ff2016-03-22 11:14:09 -0700334 RTC_DCHECK(c_name);
kwiberg352444f2016-11-28 15:58:53 -0800335 RTC_DCHECK_LT(strlen(c_name), RTCP_CNAME_SIZE);
danilchap56036ff2016-03-22 11:14:09 -0700336 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200337 if (csrc_cnames_.size() >= kRtpCsrcSize)
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000338 return -1;
Erik Språng0ea42d32015-06-25 14:46:16 +0200339
340 csrc_cnames_[SSRC] = c_name;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000341 return 0;
342}
343
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000344int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
danilchap56036ff2016-03-22 11:14:09 -0700345 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200346 auto it = csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000347
Erik Språng242e22b2015-05-11 10:17:43 +0200348 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000349 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200350
Erik Språng242e22b2015-05-11 10:17:43 +0200351 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000352 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000353}
354
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000355bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
danilchap162abd32015-12-10 02:39:40 -0800356 /*
357 For audio we use a fix 5 sec interval
niklase@google.com470e71d2011-07-07 08:21:25 +0000358
danilchap162abd32015-12-10 02:39:40 -0800359 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
360 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
361 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000362
363
danilchap162abd32015-12-10 02:39:40 -0800364 From RFC 3550
niklase@google.com470e71d2011-07-07 08:21:25 +0000365
danilchap162abd32015-12-10 02:39:40 -0800366 MAX RTCP BW is 5% if the session BW
367 A send report is approximately 65 bytes inc CNAME
368 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000369
danilchap162abd32015-12-10 02:39:40 -0800370 The RECOMMENDED value for the reduced minimum in seconds is 360
371 divided by the session bandwidth in kilobits/second. This minimum
372 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
niklase@google.com470e71d2011-07-07 08:21:25 +0000373
danilchap162abd32015-12-10 02:39:40 -0800374 If the participant has not yet sent an RTCP packet (the variable
375 initial is true), the constant Tmin is set to 2.5 seconds, else it
376 is set to 5 seconds.
niklase@google.com470e71d2011-07-07 08:21:25 +0000377
danilchap162abd32015-12-10 02:39:40 -0800378 The interval between RTCP packets is varied randomly over the
379 range [0.5,1.5] times the calculated interval to avoid unintended
380 synchronization of all participants
niklase@google.com470e71d2011-07-07 08:21:25 +0000381
danilchap162abd32015-12-10 02:39:40 -0800382 if we send
383 If the participant is a sender (we_sent true), the constant C is
384 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
385 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
386 number of senders.
niklase@google.com470e71d2011-07-07 08:21:25 +0000387
danilchap162abd32015-12-10 02:39:40 -0800388 if we receive only
389 If we_sent is not true, the constant C is set
390 to the average RTCP packet size divided by 75% of the RTCP
391 bandwidth. The constant n is set to the number of receivers
392 (members - senders). If the number of senders is greater than
393 25%, senders and receivers are treated together.
niklase@google.com470e71d2011-07-07 08:21:25 +0000394
danilchap162abd32015-12-10 02:39:40 -0800395 reconsideration NOT required for peer-to-peer
396 "timer reconsideration" is
397 employed. This algorithm implements a simple back-off mechanism
398 which causes users to hold back RTCP packet transmission if the
399 group sizes are increasing.
niklase@google.com470e71d2011-07-07 08:21:25 +0000400
danilchap162abd32015-12-10 02:39:40 -0800401 n = number of members
402 C = avg_size/(rtcpBW/4)
niklase@google.com470e71d2011-07-07 08:21:25 +0000403
danilchap162abd32015-12-10 02:39:40 -0800404 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
niklase@google.com470e71d2011-07-07 08:21:25 +0000405
danilchap162abd32015-12-10 02:39:40 -0800406 4. The calculated interval T is set to a number uniformly distributed
407 between 0.5 and 1.5 times the deterministic calculated interval.
niklase@google.com470e71d2011-07-07 08:21:25 +0000408
danilchap162abd32015-12-10 02:39:40 -0800409 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
410 for the fact that the timer reconsideration algorithm converges to
411 a value of the RTCP bandwidth below the intended average
412 */
niklase@google.com470e71d2011-07-07 08:21:25 +0000413
Erik Språng242e22b2015-05-11 10:17:43 +0200414 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000415
danilchap56036ff2016-03-22 11:14:09 -0700416 rtc::CritScope lock(&critical_section_rtcp_sender_);
xians@webrtc.org8738d272011-11-25 13:43:53 +0000417
pbosda903ea2015-10-02 02:36:56 -0700418 if (method_ == RtcpMode::kOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000419 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000420
Erik Språng242e22b2015-05-11 10:17:43 +0200421 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200422 // for video key-frames we want to send the RTCP before the large key-frame
423 // if we have a 100 ms margin
424 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
425 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000426
Erik Språng242e22b2015-05-11 10:17:43 +0200427 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200428 return true;
429 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200430 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200431 // wrap
432 return true;
433 }
434 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000435}
436
danilchap56036ff2016-03-22 11:14:09 -0700437std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSR(const RtcpContext& ctx) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200438 // Timestamp shouldn't be estimated before first media frame.
439 RTC_DCHECK_GE(last_frame_capture_time_ms_, 0);
Erik Språng61be2a42015-04-27 13:32:52 +0200440 // The timestamp of this RTCP packet should be estimated as the timestamp of
441 // the frame being captured at this moment. We are calculating that
442 // timestamp as the last frame's timestamp + the time since the last frame
443 // was captured.
solenbergb19d2882016-10-03 06:22:25 -0700444 uint32_t rtp_rate =
445 (audio_ ? kBogusRtpRateForAudioRtcp : kVideoPayloadTypeFrequency) / 1000;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200446 uint32_t rtp_timestamp =
danilchap71fead22016-08-18 02:01:49 -0700447 timestamp_offset_ + last_rtp_timestamp_ +
solenbergb19d2882016-10-03 06:22:25 -0700448 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) * rtp_rate;
niklase@google.com470e71d2011-07-07 08:21:25 +0000449
Erik Språngf7c57762015-12-04 10:40:35 +0100450 rtcp::SenderReport* report = new rtcp::SenderReport();
danilchap822a16f2016-09-27 09:27:47 -0700451 report->SetSenderSsrc(ssrc_);
danilchap51813b32016-12-16 02:44:36 -0800452 report->SetNtp(ctx.now_);
danilchap822a16f2016-09-27 09:27:47 -0700453 report->SetRtpTimestamp(rtp_timestamp);
454 report->SetPacketCount(ctx.feedback_state_.packets_sent);
455 report->SetOctetCount(ctx.feedback_state_.media_bytes_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000456
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200457 for (auto it : report_blocks_)
danilchap822a16f2016-09-27 09:27:47 -0700458 report->AddReportBlock(it.second);
niklase@google.com470e71d2011-07-07 08:21:25 +0000459
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200460 report_blocks_.clear();
Erik Språngf7c57762015-12-04 10:40:35 +0100461
danilchap56036ff2016-03-22 11:14:09 -0700462 return std::unique_ptr<rtcp::RtcpPacket>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000463}
464
danilchap56036ff2016-03-22 11:14:09 -0700465std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSDES(
Erik Språngf7c57762015-12-04 10:40:35 +0100466 const RtcpContext& ctx) {
Erik Språng0ea42d32015-06-25 14:46:16 +0200467 size_t length_cname = cname_.length();
kwiberg352444f2016-11-28 15:58:53 -0800468 RTC_CHECK_LT(length_cname, RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000469
Erik Språngf7c57762015-12-04 10:40:35 +0100470 rtcp::Sdes* sdes = new rtcp::Sdes();
danilchap822a16f2016-09-27 09:27:47 -0700471 sdes->AddCName(ssrc_, cname_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200472
473 for (const auto it : csrc_cnames_)
danilchap822a16f2016-09-27 09:27:47 -0700474 sdes->AddCName(it.first, it.second);
Erik Språng0ea42d32015-06-25 14:46:16 +0200475
danilchap56036ff2016-03-22 11:14:09 -0700476 return std::unique_ptr<rtcp::RtcpPacket>(sdes);
niklase@google.com470e71d2011-07-07 08:21:25 +0000477}
478
danilchap56036ff2016-03-22 11:14:09 -0700479std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildRR(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100480 rtcp::ReceiverReport* report = new rtcp::ReceiverReport();
danilchap822a16f2016-09-27 09:27:47 -0700481 report->SetSenderSsrc(ssrc_);
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200482 for (auto it : report_blocks_)
danilchap822a16f2016-09-27 09:27:47 -0700483 report->AddReportBlock(it.second);
Erik Språng61be2a42015-04-27 13:32:52 +0200484
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200485 report_blocks_.clear();
danilchap56036ff2016-03-22 11:14:09 -0700486 return std::unique_ptr<rtcp::RtcpPacket>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000487}
488
danilchap56036ff2016-03-22 11:14:09 -0700489std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildPLI(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100490 rtcp::Pli* pli = new rtcp::Pli();
danilchap822a16f2016-09-27 09:27:47 -0700491 pli->SetSenderSsrc(ssrc_);
492 pli->SetMediaSsrc(remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200493
Erik Språng242e22b2015-05-11 10:17:43 +0200494 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
495 "RTCPSender::PLI");
496 ++packet_type_counter_.pli_packets;
497 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
498 ssrc_, packet_type_counter_.pli_packets);
499
danilchap56036ff2016-03-22 11:14:09 -0700500 return std::unique_ptr<rtcp::RtcpPacket>(pli);
Erik Språng61be2a42015-04-27 13:32:52 +0200501}
502
danilchap56036ff2016-03-22 11:14:09 -0700503std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildFIR(const RtcpContext& ctx) {
danilchap498ee8e2017-02-08 05:24:31 -0800504 ++sequence_number_fir_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000505
Erik Språngf7c57762015-12-04 10:40:35 +0100506 rtcp::Fir* fir = new rtcp::Fir();
danilchap822a16f2016-09-27 09:27:47 -0700507 fir->SetSenderSsrc(ssrc_);
508 fir->AddRequestTo(remote_ssrc_, sequence_number_fir_);
Erik Språng242e22b2015-05-11 10:17:43 +0200509
510 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
511 "RTCPSender::FIR");
512 ++packet_type_counter_.fir_packets;
513 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
514 ssrc_, packet_type_counter_.fir_packets);
515
danilchap56036ff2016-03-22 11:14:09 -0700516 return std::unique_ptr<rtcp::RtcpPacket>(fir);
niklase@google.com470e71d2011-07-07 08:21:25 +0000517}
518
519/*
520 0 1 2 3
521 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
522 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
523 | First | Number | PictureID |
524 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
525*/
danilchap56036ff2016-03-22 11:14:09 -0700526std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSLI(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100527 rtcp::Sli* sli = new rtcp::Sli();
danilchap822a16f2016-09-27 09:27:47 -0700528 sli->SetSenderSsrc(ssrc_);
529 sli->SetMediaSsrc(remote_ssrc_);
sprang0365a272015-08-11 01:02:37 -0700530 // Crop picture id to 6 least significant bits.
danilchap822a16f2016-09-27 09:27:47 -0700531 sli->AddPictureId(ctx.picture_id_ & 0x3F);
sprang0365a272015-08-11 01:02:37 -0700532
danilchap56036ff2016-03-22 11:14:09 -0700533 return std::unique_ptr<rtcp::RtcpPacket>(sli);
niklase@google.com470e71d2011-07-07 08:21:25 +0000534}
535
536/*
537 0 1 2 3
538 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
539 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
540 | PB |0| Payload Type| Native RPSI bit string |
541 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
542 | defined per codec ... | Padding (0) |
543 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
544*/
545/*
546* Note: not generic made for VP8
547*/
danilchap56036ff2016-03-22 11:14:09 -0700548std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildRPSI(
Erik Språngf7c57762015-12-04 10:40:35 +0100549 const RtcpContext& ctx) {
550 if (ctx.feedback_state_.send_payload_type == 0xFF)
551 return nullptr;
Erik Språng242e22b2015-05-11 10:17:43 +0200552
Erik Språngf7c57762015-12-04 10:40:35 +0100553 rtcp::Rpsi* rpsi = new rtcp::Rpsi();
danilchap822a16f2016-09-27 09:27:47 -0700554 rpsi->SetSenderSsrc(ssrc_);
555 rpsi->SetMediaSsrc(remote_ssrc_);
556 rpsi->SetPayloadType(ctx.feedback_state_.send_payload_type);
557 rpsi->SetPictureId(ctx.picture_id_);
sprangcf7f54d2015-08-13 04:37:42 -0700558
danilchap56036ff2016-03-22 11:14:09 -0700559 return std::unique_ptr<rtcp::RtcpPacket>(rpsi);
niklase@google.com470e71d2011-07-07 08:21:25 +0000560}
561
danilchap56036ff2016-03-22 11:14:09 -0700562std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildREMB(
Erik Språngf7c57762015-12-04 10:40:35 +0100563 const RtcpContext& ctx) {
564 rtcp::Remb* remb = new rtcp::Remb();
danilchap822a16f2016-09-27 09:27:47 -0700565 remb->SetSenderSsrc(ssrc_);
566 remb->SetBitrateBps(remb_bitrate_);
567 remb->SetSsrcs(remb_ssrcs_);
Erik Språng61be2a42015-04-27 13:32:52 +0200568
Erik Språng242e22b2015-05-11 10:17:43 +0200569 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
570 "RTCPSender::REMB");
571
danilchap56036ff2016-03-22 11:14:09 -0700572 return std::unique_ptr<rtcp::RtcpPacket>(remb);
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000573}
574
Erik Språng61be2a42015-04-27 13:32:52 +0200575void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
danilchap56036ff2016-03-22 11:14:09 -0700576 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap2b616392016-08-18 06:17:42 -0700577 tmmbr_send_bps_ = target_bitrate;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000578}
579
danilchap56036ff2016-03-22 11:14:09 -0700580std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBR(
Erik Språngf7c57762015-12-04 10:40:35 +0100581 const RtcpContext& ctx) {
582 if (ctx.feedback_state_.module == nullptr)
583 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200584 // Before sending the TMMBR check the received TMMBN, only an owner is
585 // allowed to raise the bitrate:
586 // * If the sender is an owner of the TMMBN -> send TMMBR
587 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000588
Erik Språng61be2a42015-04-27 13:32:52 +0200589 // get current bounding set from RTCP receiver
danilchap2b616392016-08-18 06:17:42 -0700590 bool tmmbr_owner = false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000591
Erik Språng242e22b2015-05-11 10:17:43 +0200592 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
593 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
Erik Språng61be2a42015-04-27 13:32:52 +0200594 // since RTCPreceiver is not doing the reverse we should be fine
danilchap2b616392016-08-18 06:17:42 -0700595 std::vector<rtcp::TmmbItem> candidates =
596 ctx.feedback_state_.module->BoundingSet(&tmmbr_owner);
niklase@google.com470e71d2011-07-07 08:21:25 +0000597
danilchap2b616392016-08-18 06:17:42 -0700598 if (!candidates.empty()) {
599 for (const auto& candidate : candidates) {
600 if (candidate.bitrate_bps() == tmmbr_send_bps_ &&
601 candidate.packet_overhead() == packet_oh_send_) {
Erik Språngf7c57762015-12-04 10:40:35 +0100602 // Do not send the same tuple.
603 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200604 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000605 }
danilchap2b616392016-08-18 06:17:42 -0700606 if (!tmmbr_owner) {
607 // Use received bounding set as candidate set.
608 // Add current tuple.
609 candidates.emplace_back(ssrc_, tmmbr_send_bps_, packet_oh_send_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000610
danilchap2b616392016-08-18 06:17:42 -0700611 // Find bounding set.
danilchap2f69ce92016-08-16 03:21:38 -0700612 std::vector<rtcp::TmmbItem> bounding =
613 TMMBRHelp::FindBoundingSet(std::move(candidates));
danilchap2b616392016-08-18 06:17:42 -0700614 tmmbr_owner = TMMBRHelp::IsOwner(bounding, ssrc_);
615 if (!tmmbr_owner) {
Erik Språngf7c57762015-12-04 10:40:35 +0100616 // Did not enter bounding set, no meaning to send this request.
617 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200618 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000619 }
Erik Språng61be2a42015-04-27 13:32:52 +0200620 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000621
danilchap2b616392016-08-18 06:17:42 -0700622 if (!tmmbr_send_bps_)
Erik Språngf7c57762015-12-04 10:40:35 +0100623 return nullptr;
sprang81a3e602015-08-21 05:30:11 -0700624
Erik Språngf7c57762015-12-04 10:40:35 +0100625 rtcp::Tmmbr* tmmbr = new rtcp::Tmmbr();
danilchap822a16f2016-09-27 09:27:47 -0700626 tmmbr->SetSenderSsrc(ssrc_);
danilchapf174e3a2016-02-05 04:56:36 -0800627 rtcp::TmmbItem request;
628 request.set_ssrc(remote_ssrc_);
danilchap2b616392016-08-18 06:17:42 -0700629 request.set_bitrate_bps(tmmbr_send_bps_);
danilchapf174e3a2016-02-05 04:56:36 -0800630 request.set_packet_overhead(packet_oh_send_);
danilchap822a16f2016-09-27 09:27:47 -0700631 tmmbr->AddTmmbr(request);
Erik Språngf7c57762015-12-04 10:40:35 +0100632
danilchap56036ff2016-03-22 11:14:09 -0700633 return std::unique_ptr<rtcp::RtcpPacket>(tmmbr);
Erik Språng61be2a42015-04-27 13:32:52 +0200634}
635
danilchap56036ff2016-03-22 11:14:09 -0700636std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBN(
Erik Språngf7c57762015-12-04 10:40:35 +0100637 const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100638 rtcp::Tmmbn* tmmbn = new rtcp::Tmmbn();
danilchap822a16f2016-09-27 09:27:47 -0700639 tmmbn->SetSenderSsrc(ssrc_);
danilchap6eaa3a42016-05-09 10:59:50 -0700640 for (const rtcp::TmmbItem& tmmbr : tmmbn_to_send_) {
641 if (tmmbr.bitrate_bps() > 0) {
danilchap822a16f2016-09-27 09:27:47 -0700642 tmmbn->AddTmmbr(tmmbr);
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000643 }
Erik Språng61be2a42015-04-27 13:32:52 +0200644 }
sprangd83df502015-08-27 01:05:08 -0700645
danilchap56036ff2016-03-22 11:14:09 -0700646 return std::unique_ptr<rtcp::RtcpPacket>(tmmbn);
niklase@google.com470e71d2011-07-07 08:21:25 +0000647}
648
danilchap56036ff2016-03-22 11:14:09 -0700649std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildAPP(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100650 rtcp::App* app = new rtcp::App();
danilchap822a16f2016-09-27 09:27:47 -0700651 app->SetSsrc(ssrc_);
652 app->SetSubType(app_sub_type_);
653 app->SetName(app_name_);
654 app->SetData(app_data_.get(), app_length_);
Erik Språng521875a2015-09-01 10:11:16 +0200655
danilchap56036ff2016-03-22 11:14:09 -0700656 return std::unique_ptr<rtcp::RtcpPacket>(app);
Erik Språng61be2a42015-04-27 13:32:52 +0200657}
658
danilchap56036ff2016-03-22 11:14:09 -0700659std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildNACK(
Erik Språngf7c57762015-12-04 10:40:35 +0100660 const RtcpContext& ctx) {
661 rtcp::Nack* nack = new rtcp::Nack();
danilchap822a16f2016-09-27 09:27:47 -0700662 nack->SetSenderSsrc(ssrc_);
663 nack->SetMediaSsrc(remote_ssrc_);
664 nack->SetPacketIds(ctx.nack_list_, ctx.nack_size_);
Erik Språng61be2a42015-04-27 13:32:52 +0200665
666 // Report stats.
667 NACKStringBuilder stringBuilder;
Erik Språngf7c57762015-12-04 10:40:35 +0100668 for (int idx = 0; idx < ctx.nack_size_; ++idx) {
669 stringBuilder.PushNACK(ctx.nack_list_[idx]);
670 nack_stats_.ReportRequest(ctx.nack_list_[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +0200671 }
Erik Språng61be2a42015-04-27 13:32:52 +0200672 packet_type_counter_.nack_requests = nack_stats_.requests();
673 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +0200674
675 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
676 "RTCPSender::NACK", "nacks",
677 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
678 ++packet_type_counter_.nack_packets;
679 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
680 ssrc_, packet_type_counter_.nack_packets);
681
danilchap56036ff2016-03-22 11:14:09 -0700682 return std::unique_ptr<rtcp::RtcpPacket>(nack);
Erik Språng61be2a42015-04-27 13:32:52 +0200683}
684
danilchap56036ff2016-03-22 11:14:09 -0700685std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildBYE(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100686 rtcp::Bye* bye = new rtcp::Bye();
danilchap822a16f2016-09-27 09:27:47 -0700687 bye->SetSenderSsrc(ssrc_);
688 bye->SetCsrcs(csrcs_);
sprangd8ee4f92015-08-24 03:25:19 -0700689
danilchap56036ff2016-03-22 11:14:09 -0700690 return std::unique_ptr<rtcp::RtcpPacket>(bye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000691}
692
sprang5e38c962016-12-01 05:18:09 -0800693std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildExtendedReports(
Erik Språngf7c57762015-12-04 10:40:35 +0100694 const RtcpContext& ctx) {
sprang5e38c962016-12-01 05:18:09 -0800695 std::unique_ptr<rtcp::ExtendedReports> xr(new rtcp::ExtendedReports());
danilchap822a16f2016-09-27 09:27:47 -0700696 xr->SetSenderSsrc(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000697
sprang5e38c962016-12-01 05:18:09 -0800698 if (!sending_ && xr_send_receiver_reference_time_enabled_) {
699 rtcp::Rrtr rrtr;
danilchap51813b32016-12-16 02:44:36 -0800700 rrtr.SetNtp(ctx.now_);
sprang5e38c962016-12-01 05:18:09 -0800701 xr->SetRrtr(rrtr);
702 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000703
sprang5e38c962016-12-01 05:18:09 -0800704 if (ctx.feedback_state_.has_last_xr_rr) {
705 xr->AddDlrrItem(ctx.feedback_state_.last_xr_rr);
706 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000707
sprang5e38c962016-12-01 05:18:09 -0800708 if (video_bitrate_allocation_) {
709 rtcp::TargetBitrate target_bitrate;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000710
sprang5e38c962016-12-01 05:18:09 -0800711 for (int sl = 0; sl < kMaxSpatialLayers; ++sl) {
712 for (int tl = 0; tl < kMaxTemporalStreams; ++tl) {
713 uint32_t layer_bitrate_bps =
714 video_bitrate_allocation_->GetBitrate(sl, tl);
715 if (layer_bitrate_bps > 0)
716 target_bitrate.AddTargetBitrate(sl, tl, layer_bitrate_bps / 1000);
717 }
718 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000719
sprang5e38c962016-12-01 05:18:09 -0800720 xr->SetTargetBitrate(target_bitrate);
721 video_bitrate_allocation_.reset();
722 }
Erik Språngca28fdc2015-08-31 14:00:50 +0200723
sprang5e38c962016-12-01 05:18:09 -0800724 if (xr_voip_metric_) {
725 rtcp::VoipMetric voip;
726 voip.SetMediaSsrc(remote_ssrc_);
727 voip.SetVoipMetric(*xr_voip_metric_);
728 xr_voip_metric_.reset();
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000729
sprang5e38c962016-12-01 05:18:09 -0800730 xr->SetVoipMetric(voip);
731 }
Erik Språngca28fdc2015-08-31 14:00:50 +0200732
sprang5e38c962016-12-01 05:18:09 -0800733 return std::move(xr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000734}
735
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000736int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200737 RTCPPacketType packetType,
738 int32_t nack_size,
739 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000740 uint64_t pictureID) {
Erik Språng242e22b2015-05-11 10:17:43 +0200741 return SendCompoundRTCP(
742 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
danilchap498ee8e2017-02-08 05:24:31 -0800743 nack_size, nack_list, pictureID);
Erik Språng242e22b2015-05-11 10:17:43 +0200744}
745
746int32_t RTCPSender::SendCompoundRTCP(
747 const FeedbackState& feedback_state,
Erik Språngf7c57762015-12-04 10:40:35 +0100748 const std::set<RTCPPacketType>& packet_types,
Erik Språng242e22b2015-05-11 10:17:43 +0200749 int32_t nack_size,
750 const uint16_t* nack_list,
Erik Språng242e22b2015-05-11 10:17:43 +0200751 uint64_t pictureID) {
terelius429c3452016-01-21 05:42:04 -0800752 PacketContainer container(transport_, event_log_);
nisse6f142eb2017-02-21 07:32:47 -0800753 size_t max_packet_size;
754
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000755 {
danilchap56036ff2016-03-22 11:14:09 -0700756 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbosda903ea2015-10-02 02:36:56 -0700757 if (method_ == RtcpMode::kOff) {
Erik Språng61be2a42015-04-27 13:32:52 +0200758 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
759 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +0000760 }
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200761 // Add all flags as volatile. Non volatile entries will not be overwritten.
762 // All new volatile flags added will be consumed by the end of this call.
763 SetFlags(packet_types, true);
764
765 // Prevent sending streams to send SR before any media has been sent.
766 const bool can_calculate_rtp_timestamp = (last_frame_capture_time_ms_ >= 0);
767 if (!can_calculate_rtp_timestamp) {
768 bool consumed_sr_flag = ConsumeFlag(kRtcpSr);
769 bool consumed_report_flag = sending_ && ConsumeFlag(kRtcpReport);
770 bool sender_report = consumed_report_flag || consumed_sr_flag;
771 if (sender_report && AllVolatileFlagsConsumed()) {
772 // This call was for Sender Report and nothing else.
773 return 0;
774 }
775 if (sending_ && method_ == RtcpMode::kCompound) {
776 // Not allowed to send any RTCP packet without sender report.
777 return -1;
778 }
779 }
780
781 if (packet_type_counter_.first_packet_time_ms == -1)
782 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språngf7c57762015-12-04 10:40:35 +0100783
784 // We need to send our NTP even if we haven't received any reports.
danilchap498ee8e2017-02-08 05:24:31 -0800785 RtcpContext context(feedback_state, nack_size, nack_list, pictureID,
danilchap37953762017-02-09 11:15:25 -0800786 clock_->CurrentNtpTime());
Erik Språngf7c57762015-12-04 10:40:35 +0100787
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200788 PrepareReport(feedback_state);
Erik Språngf7c57762015-12-04 10:40:35 +0100789
danilchap56036ff2016-03-22 11:14:09 -0700790 std::unique_ptr<rtcp::RtcpPacket> packet_bye;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800791
Erik Språngf7c57762015-12-04 10:40:35 +0100792 auto it = report_flags_.begin();
793 while (it != report_flags_.end()) {
794 auto builder_it = builders_.find(it->type);
sprang5e38c962016-12-01 05:18:09 -0800795 RTC_DCHECK(builder_it != builders_.end())
796 << "Could not find builder for packet type " << it->type;
Erik Språngf7c57762015-12-04 10:40:35 +0100797 if (it->is_volatile) {
798 report_flags_.erase(it++);
799 } else {
800 ++it;
801 }
802
803 BuilderFunc func = builder_it->second;
danilchap56036ff2016-03-22 11:14:09 -0700804 std::unique_ptr<rtcp::RtcpPacket> packet = (this->*func)(context);
Erik Språngf7c57762015-12-04 10:40:35 +0100805 if (packet.get() == nullptr)
806 return -1;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800807 // If there is a BYE, don't append now - save it and append it
808 // at the end later.
809 if (builder_it->first == kRtcpBye) {
810 packet_bye = std::move(packet);
811 } else {
812 container.Append(packet.release());
813 }
814 }
815
816 // Append the BYE now at the end
817 if (packet_bye) {
818 container.Append(packet_bye.release());
Erik Språngf7c57762015-12-04 10:40:35 +0100819 }
820
821 if (packet_type_counter_observer_ != nullptr) {
822 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
823 remote_ssrc_, packet_type_counter_);
824 }
825
826 RTC_DCHECK(AllVolatileFlagsConsumed());
nisse6f142eb2017-02-21 07:32:47 -0800827 max_packet_size = max_packet_size_;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000828 }
Erik Språng61be2a42015-04-27 13:32:52 +0200829
nisse6f142eb2017-02-21 07:32:47 -0800830 size_t bytes_sent = container.SendPackets(max_packet_size);
Erik Språngf7c57762015-12-04 10:40:35 +0100831 return bytes_sent == 0 ? -1 : 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000832}
833
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200834void RTCPSender::PrepareReport(const FeedbackState& feedback_state) {
Erik Språng242e22b2015-05-11 10:17:43 +0200835 bool generate_report;
836 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
837 // Report type already explicitly set, don't automatically populate.
838 generate_report = true;
henrikg91d6ede2015-09-17 00:24:34 -0700839 RTC_DCHECK(ConsumeFlag(kRtcpReport) == false);
Erik Språng242e22b2015-05-11 10:17:43 +0200840 } else {
841 generate_report =
pbosda903ea2015-10-02 02:36:56 -0700842 (ConsumeFlag(kRtcpReport) && method_ == RtcpMode::kReducedSize) ||
843 method_ == RtcpMode::kCompound;
Erik Språng242e22b2015-05-11 10:17:43 +0200844 if (generate_report)
845 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000846 }
847
Erik Språng0ea42d32015-06-25 14:46:16 +0200848 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
Erik Språng242e22b2015-05-11 10:17:43 +0200849 SetFlag(kRtcpSdes, true);
850
Erik Språng242e22b2015-05-11 10:17:43 +0200851 if (generate_report) {
sprang5e38c962016-12-01 05:18:09 -0800852 if ((!sending_ && xr_send_receiver_reference_time_enabled_) ||
853 feedback_state.has_last_xr_rr || video_bitrate_allocation_) {
854 SetFlag(kRtcpAnyExtendedReports, true);
855 }
Erik Språng242e22b2015-05-11 10:17:43 +0200856
857 // generate next time to send an RTCP report
danilchap47a740b2015-12-15 00:30:07 -0800858 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000859
danilchap47a740b2015-12-15 00:30:07 -0800860 if (!audio_) {
Erik Språng242e22b2015-05-11 10:17:43 +0200861 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200862 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
863 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
864 if (send_bitrate_kbit != 0)
865 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000866 }
Erik Språng61be2a42015-04-27 13:32:52 +0200867 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
868 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
Erik Språng61be2a42015-04-27 13:32:52 +0200869 }
danilchap47a740b2015-12-15 00:30:07 -0800870 // The interval between RTCP packets is varied randomly over the
871 // range [1/2,3/2] times the calculated interval.
872 uint32_t timeToNext =
873 random_.Rand(minIntervalMs * 1 / 2, minIntervalMs * 3 / 2);
Erik Språng242e22b2015-05-11 10:17:43 +0200874 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000875
Per83d09102016-04-15 14:59:13 +0200876 if (receive_statistics_) {
877 StatisticianMap statisticians =
878 receive_statistics_->GetActiveStatisticians();
879 RTC_DCHECK(report_blocks_.empty());
880 for (auto& it : statisticians) {
881 AddReportBlock(feedback_state, it.first, it.second);
882 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000883 }
884 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000885}
886
danilchapa72e7342015-12-22 08:07:45 -0800887bool RTCPSender::AddReportBlock(const FeedbackState& feedback_state,
888 uint32_t ssrc,
889 StreamStatistician* statistician) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000890 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000891 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000892 if (!statistician->GetStatistics(&stats, true))
893 return false;
danilchapa72e7342015-12-22 08:07:45 -0800894
895 if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) {
896 LOG(LS_WARNING) << "Too many report blocks.";
897 return false;
898 }
899 RTC_DCHECK(report_blocks_.find(ssrc) == report_blocks_.end());
900 rtcp::ReportBlock* block = &report_blocks_[ssrc];
danilchap822a16f2016-09-27 09:27:47 -0700901 block->SetMediaSsrc(ssrc);
902 block->SetFractionLost(stats.fraction_lost);
903 if (!block->SetCumulativeLost(stats.cumulative_lost)) {
danilchapa72e7342015-12-22 08:07:45 -0800904 report_blocks_.erase(ssrc);
905 LOG(LS_WARNING) << "Cumulative lost is oversized.";
906 return false;
907 }
danilchap822a16f2016-09-27 09:27:47 -0700908 block->SetExtHighestSeqNum(stats.extended_max_sequence_number);
909 block->SetJitter(stats.jitter);
910 block->SetLastSr(feedback_state.remote_sr);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000911
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200912 // TODO(sprang): Do we really need separate time stamps for each report?
913 // Get our NTP as late as possible to avoid a race.
danilchap42287842017-02-20 06:40:18 -0800914 NtpTime ntp = clock_->CurrentNtpTime();
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000915
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200916 // Delay since last received report.
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000917 if ((feedback_state.last_rr_ntp_secs != 0) ||
918 (feedback_state.last_rr_ntp_frac != 0)) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200919 // Get the 16 lowest bits of seconds and the 16 highest bits of fractions.
danilchap42287842017-02-20 06:40:18 -0800920 uint32_t now = CompactNtp(ntp);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000921
Erik Språng61be2a42015-04-27 13:32:52 +0200922 uint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
923 receiveTime <<= 16;
924 receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000925
danilchap822a16f2016-09-27 09:27:47 -0700926 block->SetDelayLastSr(now - receiveTime);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000927 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000928 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000929}
930
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000931void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
kwiberg352444f2016-11-28 15:58:53 -0800932 RTC_DCHECK_LE(csrcs.size(), kRtpCsrcSize);
danilchap56036ff2016-03-22 11:14:09 -0700933 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000934 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +0000935}
936
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000937int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
938 uint32_t name,
939 const uint8_t* data,
940 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +0200941 if (length % 4 != 0) {
942 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
943 return -1;
944 }
danilchap56036ff2016-03-22 11:14:09 -0700945 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000946
Erik Språng242e22b2015-05-11 10:17:43 +0200947 SetFlag(kRtcpApp, true);
948 app_sub_type_ = subType;
949 app_name_ = name;
950 app_data_.reset(new uint8_t[length]);
951 app_length_ = length;
952 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +0200953 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000954}
955
spranga790d832016-12-02 07:29:44 -0800956// TODO(sprang): Remove support for VoIP metrics? (Not used in receiver.)
Erik Språng61be2a42015-04-27 13:32:52 +0200957int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
danilchap56036ff2016-03-22 11:14:09 -0700958 rtc::CritScope lock(&critical_section_rtcp_sender_);
sprang5e38c962016-12-01 05:18:09 -0800959 xr_voip_metric_.emplace(*VoIPMetric);
niklase@google.com470e71d2011-07-07 08:21:25 +0000960
sprang5e38c962016-12-01 05:18:09 -0800961 SetFlag(kRtcpAnyExtendedReports, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200962 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000963}
964
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000965void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700966 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200967 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000968}
969
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000970bool RTCPSender::RtcpXrReceiverReferenceTime() const {
danilchap56036ff2016-03-22 11:14:09 -0700971 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200972 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000973}
974
danilchap853ecb22016-08-22 08:26:15 -0700975void RTCPSender::SetTmmbn(std::vector<rtcp::TmmbItem> bounding_set) {
danilchap56036ff2016-03-22 11:14:09 -0700976 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap853ecb22016-08-22 08:26:15 -0700977 tmmbn_to_send_ = std::move(bounding_set);
danilchap6eaa3a42016-05-09 10:59:50 -0700978 SetFlag(kRtcpTmmbn, true);
niklase@google.com470e71d2011-07-07 08:21:25 +0000979}
Erik Språng61be2a42015-04-27 13:32:52 +0200980
sprang5e38c962016-12-01 05:18:09 -0800981void RTCPSender::SetFlag(uint32_t type, bool is_volatile) {
982 if (type & kRtcpAnyExtendedReports) {
983 report_flags_.insert(ReportFlag(kRtcpAnyExtendedReports, is_volatile));
984 } else {
985 report_flags_.insert(ReportFlag(type, is_volatile));
986 }
Erik Språng242e22b2015-05-11 10:17:43 +0200987}
988
989void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
990 bool is_volatile) {
991 for (RTCPPacketType type : types)
992 SetFlag(type, is_volatile);
993}
994
sprang5e38c962016-12-01 05:18:09 -0800995bool RTCPSender::IsFlagPresent(uint32_t type) const {
Erik Språng242e22b2015-05-11 10:17:43 +0200996 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
997}
998
sprang5e38c962016-12-01 05:18:09 -0800999bool RTCPSender::ConsumeFlag(uint32_t type, bool forced) {
Erik Språng242e22b2015-05-11 10:17:43 +02001000 auto it = report_flags_.find(ReportFlag(type, false));
1001 if (it == report_flags_.end())
1002 return false;
1003 if (it->is_volatile || forced)
1004 report_flags_.erase((it));
1005 return true;
1006}
1007
1008bool RTCPSender::AllVolatileFlagsConsumed() const {
1009 for (const ReportFlag& flag : report_flags_) {
1010 if (flag.is_volatile)
1011 return false;
1012 }
1013 return true;
1014}
1015
sprang5e38c962016-12-01 05:18:09 -08001016void RTCPSender::SetVideoBitrateAllocation(const BitrateAllocation& bitrate) {
1017 rtc::CritScope lock(&critical_section_rtcp_sender_);
1018 video_bitrate_allocation_.emplace(bitrate);
1019 SetFlag(kRtcpAnyExtendedReports, true);
1020}
1021
sprang233bd872015-09-08 13:25:16 -07001022bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
sprang233bd872015-09-08 13:25:16 -07001023 class Sender : public rtcp::RtcpPacket::PacketReadyCallback {
1024 public:
terelius429c3452016-01-21 05:42:04 -08001025 Sender(Transport* transport, RtcEventLog* event_log)
1026 : transport_(transport), event_log_(event_log), send_failure_(false) {}
sprang233bd872015-09-08 13:25:16 -07001027
1028 void OnPacketReady(uint8_t* data, size_t length) override {
terelius429c3452016-01-21 05:42:04 -08001029 if (transport_->SendRtcp(data, length)) {
1030 if (event_log_) {
1031 event_log_->LogRtcpPacket(kOutgoingPacket, MediaType::ANY, data,
1032 length);
1033 }
1034 } else {
sprang233bd872015-09-08 13:25:16 -07001035 send_failure_ = true;
terelius429c3452016-01-21 05:42:04 -08001036 }
sprang233bd872015-09-08 13:25:16 -07001037 }
1038
1039 Transport* const transport_;
terelius429c3452016-01-21 05:42:04 -08001040 RtcEventLog* const event_log_;
sprang233bd872015-09-08 13:25:16 -07001041 bool send_failure_;
terelius429c3452016-01-21 05:42:04 -08001042 // TODO(terelius): We would like to
1043 // RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(Sender);
1044 // but we can't because of an incorrect warning (C4822) in MVS 2013.
1045 } sender(transport_, event_log_);
sprang233bd872015-09-08 13:25:16 -07001046
nisse6f142eb2017-02-21 07:32:47 -08001047 size_t max_packet_size;
stefanb77c7162017-02-06 06:29:38 -08001048 {
1049 rtc::CritScope lock(&critical_section_rtcp_sender_);
1050 if (method_ == RtcpMode::kOff)
1051 return false;
nisse6f142eb2017-02-21 07:32:47 -08001052 max_packet_size = max_packet_size_;
stefanb77c7162017-02-06 06:29:38 -08001053 }
1054
nisse6f142eb2017-02-21 07:32:47 -08001055 RTC_DCHECK_LE(max_packet_size, IP_PACKET_SIZE);
sprang233bd872015-09-08 13:25:16 -07001056 uint8_t buffer[IP_PACKET_SIZE];
nisse6f142eb2017-02-21 07:32:47 -08001057 return packet.BuildExternalBuffer(buffer, max_packet_size, &sender) &&
sprang233bd872015-09-08 13:25:16 -07001058 !sender.send_failure_;
1059}
1060
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001061} // namespace webrtc