blob: 95bfeeea1f6ba6c564109abda64174f3ffa42188 [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
Erik Språng61be2a42015-04-27 13:32:52 +020015#include "webrtc/base/checks.h"
Peter Boströmebc0b4e2015-10-28 16:39:33 +010016#include "webrtc/base/logging.h"
tommie4f96502015-10-20 23:00:48 -070017#include "webrtc/base/trace_event.h"
terelius429c3452016-01-21 05:42:04 -080018#include "webrtc/call.h"
19#include "webrtc/call/rtc_event_log.h"
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000020#include "webrtc/common_types.h"
danilchap0219c9b2015-11-18 05:56:53 -080021#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/app.h"
danilchap50c51362015-11-22 09:03:11 -080022#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/bye.h"
danilchap2f7dea12016-01-13 02:03:04 -080023#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/compound_packet.h"
Danil Chapovalov256e5b22016-01-15 14:16:24 +010024#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_reports.h"
Danil Chapovalov5679da12016-01-15 13:19:53 +010025#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/fir.h"
danilchapa8890a52015-12-22 03:43:04 -080026#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/nack.h"
danilchapf8385ad2015-11-27 05:36:09 -080027#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/pli.h"
Danil Chapovalov97f7e132015-12-04 16:13:30 +010028#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
Danil Chapovalova5eba6c2016-01-15 12:40:15 +010029#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/remb.h"
Danil Chapovalov2c132972016-01-15 15:21:21 +010030#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rpsi.h"
Danil Chapovalov1567d0b2016-01-15 17:34:27 +010031#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sdes.h"
danilchap34ed2b92016-01-18 02:43:32 -080032#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sender_report.h"
danilchap92e677a2016-01-12 10:04:52 -080033#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sli.h"
danilchapef3d8052016-01-11 03:31:08 -080034#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbn.h"
danilchap7e8145f2016-01-11 11:49:19 -080035#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbr.h"
sprang233bd872015-09-08 13:25:16 -070036#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
tommie4f96502015-10-20 23:00:48 -070037#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000038
niklase@google.com470e71d2011-07-07 08:21:25 +000039namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000040
Erik Språng61be2a42015-04-27 13:32:52 +020041NACKStringBuilder::NACKStringBuilder()
danilchap162abd32015-12-10 02:39:40 -080042 : stream_(""), count_(0), prevNack_(0), consecutive_(false) {}
edjee@google.com79b02892013-04-04 19:43:34 +000043
pbos@webrtc.orgf3e4cee2013-07-31 15:17:19 +000044NACKStringBuilder::~NACKStringBuilder() {}
45
danilchap162abd32015-12-10 02:39:40 -080046void NACKStringBuilder::PushNACK(uint16_t nack) {
Erik Språng242e22b2015-05-11 10:17:43 +020047 if (count_ == 0) {
48 stream_ << nack;
49 } else if (nack == prevNack_ + 1) {
50 consecutive_ = true;
Erik Språng61be2a42015-04-27 13:32:52 +020051 } else {
Erik Språng242e22b2015-05-11 10:17:43 +020052 if (consecutive_) {
53 stream_ << "-" << prevNack_;
54 consecutive_ = false;
edjee@google.com79b02892013-04-04 19:43:34 +000055 }
Erik Språng242e22b2015-05-11 10:17:43 +020056 stream_ << "," << nack;
Erik Språng61be2a42015-04-27 13:32:52 +020057 }
Erik Språng242e22b2015-05-11 10:17:43 +020058 count_++;
59 prevNack_ = nack;
edjee@google.com79b02892013-04-04 19:43:34 +000060}
61
Erik Språng61be2a42015-04-27 13:32:52 +020062std::string NACKStringBuilder::GetResult() {
Erik Språng242e22b2015-05-11 10:17:43 +020063 if (consecutive_) {
64 stream_ << "-" << prevNack_;
65 consecutive_ = false;
Erik Språng61be2a42015-04-27 13:32:52 +020066 }
Erik Språng242e22b2015-05-11 10:17:43 +020067 return stream_.str();
edjee@google.com79b02892013-04-04 19:43:34 +000068}
69
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000070RTCPSender::FeedbackState::FeedbackState()
71 : send_payload_type(0),
72 frequency_hz(0),
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +000073 packets_sent(0),
74 media_bytes_sent(0),
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000075 send_bitrate(0),
76 last_rr_ntp_secs(0),
77 last_rr_ntp_frac(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000078 remote_sr(0),
Erik Språng61be2a42015-04-27 13:32:52 +020079 has_last_xr_rr(false),
danilchap162abd32015-12-10 02:39:40 -080080 module(nullptr) {}
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000081
danilchap2f7dea12016-01-13 02:03:04 -080082class PacketContainer : public rtcp::CompoundPacket,
Erik Språngf7c57762015-12-04 10:40:35 +010083 public rtcp::RtcpPacket::PacketReadyCallback {
84 public:
terelius429c3452016-01-21 05:42:04 -080085 PacketContainer(Transport* transport, RtcEventLog* event_log)
86 : transport_(transport), event_log_(event_log), bytes_sent_(0) {}
Erik Språngf7c57762015-12-04 10:40:35 +010087 virtual ~PacketContainer() {
88 for (RtcpPacket* packet : appended_packets_)
89 delete packet;
90 }
91
92 void OnPacketReady(uint8_t* data, size_t length) override {
terelius429c3452016-01-21 05:42:04 -080093 if (transport_->SendRtcp(data, length)) {
Erik Språngf7c57762015-12-04 10:40:35 +010094 bytes_sent_ += length;
terelius429c3452016-01-21 05:42:04 -080095 if (event_log_) {
96 event_log_->LogRtcpPacket(kOutgoingPacket, MediaType::ANY, data,
97 length);
98 }
99 }
Erik Språngf7c57762015-12-04 10:40:35 +0100100 }
101
danilchap41befce2016-03-30 11:11:51 -0700102 size_t SendPackets(size_t max_payload_length) {
103 RTC_DCHECK_LE(max_payload_length, static_cast<size_t>(IP_PACKET_SIZE));
104 uint8_t buffer[IP_PACKET_SIZE];
105 BuildExternalBuffer(buffer, max_payload_length, this);
Erik Språngf7c57762015-12-04 10:40:35 +0100106 return bytes_sent_;
107 }
108
109 private:
110 Transport* transport_;
terelius429c3452016-01-21 05:42:04 -0800111 RtcEventLog* const event_log_;
Erik Språngf7c57762015-12-04 10:40:35 +0100112 size_t bytes_sent_;
terelius429c3452016-01-21 05:42:04 -0800113
114 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(PacketContainer);
Erik Språngf7c57762015-12-04 10:40:35 +0100115};
116
117class RTCPSender::RtcpContext {
118 public:
Erik Språng242e22b2015-05-11 10:17:43 +0200119 RtcpContext(const FeedbackState& feedback_state,
120 int32_t nack_size,
121 const uint16_t* nack_list,
122 bool repeat,
123 uint64_t picture_id,
Erik Språngf7c57762015-12-04 10:40:35 +0100124 uint32_t ntp_sec,
danilchap56036ff2016-03-22 11:14:09 -0700125 uint32_t ntp_frac)
Erik Språngf7c57762015-12-04 10:40:35 +0100126 : feedback_state_(feedback_state),
127 nack_size_(nack_size),
128 nack_list_(nack_list),
129 repeat_(repeat),
130 picture_id_(picture_id),
131 ntp_sec_(ntp_sec),
danilchap56036ff2016-03-22 11:14:09 -0700132 ntp_frac_(ntp_frac) {}
Erik Språng242e22b2015-05-11 10:17:43 +0200133
Erik Språngf7c57762015-12-04 10:40:35 +0100134 const FeedbackState& feedback_state_;
135 const int32_t nack_size_;
136 const uint16_t* nack_list_;
137 const bool repeat_;
138 const uint64_t picture_id_;
139 const uint32_t ntp_sec_;
140 const uint32_t ntp_frac_;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200141};
142
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000143RTCPSender::RTCPSender(
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000144 bool audio,
145 Clock* clock,
146 ReceiveStatistics* receive_statistics,
sprang86fd9ed2015-09-29 04:45:43 -0700147 RtcpPacketTypeCounterObserver* packet_type_counter_observer,
terelius429c3452016-01-21 05:42:04 -0800148 RtcEventLog* event_log,
sprang86fd9ed2015-09-29 04:45:43 -0700149 Transport* outgoing_transport)
Peter Boströmac547a62015-09-17 23:03:57 +0200150 : audio_(audio),
Erik Språng242e22b2015-05-11 10:17:43 +0200151 clock_(clock),
danilchap47a740b2015-12-15 00:30:07 -0800152 random_(clock_->TimeInMicroseconds()),
pbosda903ea2015-10-02 02:36:56 -0700153 method_(RtcpMode::kOff),
terelius429c3452016-01-21 05:42:04 -0800154 event_log_(event_log),
sprang86fd9ed2015-09-29 04:45:43 -0700155 transport_(outgoing_transport),
Erik Språng242e22b2015-05-11 10:17:43 +0200156 using_nack_(false),
157 sending_(false),
158 remb_enabled_(false),
Erik Språng242e22b2015-05-11 10:17:43 +0200159 next_time_to_send_rtcp_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000160 start_timestamp_(0),
161 last_rtp_timestamp_(0),
162 last_frame_capture_time_ms_(-1),
Erik Språng242e22b2015-05-11 10:17:43 +0200163 ssrc_(0),
164 remote_ssrc_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000165 receive_statistics_(receive_statistics),
niklase@google.com470e71d2011-07-07 08:21:25 +0000166
Erik Språng242e22b2015-05-11 10:17:43 +0200167 sequence_number_fir_(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000168
Erik Språng242e22b2015-05-11 10:17:43 +0200169 remb_bitrate_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000170
Erik Språng242e22b2015-05-11 10:17:43 +0200171 tmmbr_help_(),
172 tmmbr_send_(0),
173 packet_oh_send_(0),
danilchap41befce2016-03-30 11:11:51 -0700174 max_payload_length_(IP_PACKET_SIZE - 28), // IPv4 + UDP by default.
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000175
Erik Språng242e22b2015-05-11 10:17:43 +0200176 app_sub_type_(0),
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200177 app_name_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200178 app_data_(nullptr),
179 app_length_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000180
Erik Språng242e22b2015-05-11 10:17:43 +0200181 xr_send_receiver_reference_time_enabled_(false),
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000182 packet_type_counter_observer_(packet_type_counter_observer) {
sprang86fd9ed2015-09-29 04:45:43 -0700183 RTC_DCHECK(transport_ != nullptr);
Erik Språng242e22b2015-05-11 10:17:43 +0200184
185 builders_[kRtcpSr] = &RTCPSender::BuildSR;
186 builders_[kRtcpRr] = &RTCPSender::BuildRR;
Erik Språng0ea42d32015-06-25 14:46:16 +0200187 builders_[kRtcpSdes] = &RTCPSender::BuildSDES;
Erik Språng242e22b2015-05-11 10:17:43 +0200188 builders_[kRtcpPli] = &RTCPSender::BuildPLI;
189 builders_[kRtcpFir] = &RTCPSender::BuildFIR;
190 builders_[kRtcpSli] = &RTCPSender::BuildSLI;
191 builders_[kRtcpRpsi] = &RTCPSender::BuildRPSI;
192 builders_[kRtcpRemb] = &RTCPSender::BuildREMB;
193 builders_[kRtcpBye] = &RTCPSender::BuildBYE;
194 builders_[kRtcpApp] = &RTCPSender::BuildAPP;
195 builders_[kRtcpTmmbr] = &RTCPSender::BuildTMMBR;
196 builders_[kRtcpTmmbn] = &RTCPSender::BuildTMMBN;
197 builders_[kRtcpNack] = &RTCPSender::BuildNACK;
198 builders_[kRtcpXrVoipMetric] = &RTCPSender::BuildVoIPMetric;
199 builders_[kRtcpXrReceiverReferenceTime] =
200 &RTCPSender::BuildReceiverReferenceTime;
201 builders_[kRtcpXrDlrrReportBlock] = &RTCPSender::BuildDlrr;
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
danilchap41befce2016-03-30 11:11:51 -0700284void RTCPSender::SetMaxPayloadLength(size_t max_payload_length) {
285 max_payload_length_ = max_payload_length;
286}
287
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000288void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
danilchap56036ff2016-03-22 11:14:09 -0700289 rtc::CritScope lock(&critical_section_rtcp_sender_);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000290 start_timestamp_ = start_timestamp;
291}
292
293void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
294 int64_t capture_time_ms) {
danilchap56036ff2016-03-22 11:14:09 -0700295 rtc::CritScope lock(&critical_section_rtcp_sender_);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000296 last_rtp_timestamp_ = rtp_timestamp;
297 if (capture_time_ms < 0) {
298 // We don't currently get a capture time from VoiceEngine.
Erik Språng242e22b2015-05-11 10:17:43 +0200299 last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000300 } else {
301 last_frame_capture_time_ms_ = capture_time_ms;
302 }
303}
304
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000305void RTCPSender::SetSSRC(uint32_t ssrc) {
danilchap56036ff2016-03-22 11:14:09 -0700306 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000307
Erik Språng242e22b2015-05-11 10:17:43 +0200308 if (ssrc_ != 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200309 // not first SetSSRC, probably due to a collision
310 // schedule a new RTCP report
311 // make sure that we send a RTP packet
Erik Språng242e22b2015-05-11 10:17:43 +0200312 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
Erik Språng61be2a42015-04-27 13:32:52 +0200313 }
Erik Språng242e22b2015-05-11 10:17:43 +0200314 ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000315}
316
Erik Språng61be2a42015-04-27 13:32:52 +0200317void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
danilchap56036ff2016-03-22 11:14:09 -0700318 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200319 remote_ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000320}
321
Peter Boström9ba52f82015-06-01 14:12:28 +0200322int32_t RTCPSender::SetCNAME(const char* c_name) {
323 if (!c_name)
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000324 return -1;
325
henrikg91d6ede2015-09-17 00:24:34 -0700326 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
danilchap56036ff2016-03-22 11:14:09 -0700327 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200328 cname_ = c_name;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000329 return 0;
330}
331
Erik Språng0ea42d32015-06-25 14:46:16 +0200332int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC, const char* c_name) {
danilchap56036ff2016-03-22 11:14:09 -0700333 RTC_DCHECK(c_name);
henrikg91d6ede2015-09-17 00:24:34 -0700334 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
danilchap56036ff2016-03-22 11:14:09 -0700335 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200336 if (csrc_cnames_.size() >= kRtpCsrcSize)
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000337 return -1;
Erik Språng0ea42d32015-06-25 14:46:16 +0200338
339 csrc_cnames_[SSRC] = c_name;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000340 return 0;
341}
342
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000343int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
danilchap56036ff2016-03-22 11:14:09 -0700344 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200345 auto it = csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000346
Erik Språng242e22b2015-05-11 10:17:43 +0200347 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000348 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200349
Erik Språng242e22b2015-05-11 10:17:43 +0200350 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000351 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000352}
353
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000354bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
danilchap162abd32015-12-10 02:39:40 -0800355 /*
356 For audio we use a fix 5 sec interval
niklase@google.com470e71d2011-07-07 08:21:25 +0000357
danilchap162abd32015-12-10 02:39:40 -0800358 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
359 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
360 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000361
362
danilchap162abd32015-12-10 02:39:40 -0800363 From RFC 3550
niklase@google.com470e71d2011-07-07 08:21:25 +0000364
danilchap162abd32015-12-10 02:39:40 -0800365 MAX RTCP BW is 5% if the session BW
366 A send report is approximately 65 bytes inc CNAME
367 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000368
danilchap162abd32015-12-10 02:39:40 -0800369 The RECOMMENDED value for the reduced minimum in seconds is 360
370 divided by the session bandwidth in kilobits/second. This minimum
371 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
niklase@google.com470e71d2011-07-07 08:21:25 +0000372
danilchap162abd32015-12-10 02:39:40 -0800373 If the participant has not yet sent an RTCP packet (the variable
374 initial is true), the constant Tmin is set to 2.5 seconds, else it
375 is set to 5 seconds.
niklase@google.com470e71d2011-07-07 08:21:25 +0000376
danilchap162abd32015-12-10 02:39:40 -0800377 The interval between RTCP packets is varied randomly over the
378 range [0.5,1.5] times the calculated interval to avoid unintended
379 synchronization of all participants
niklase@google.com470e71d2011-07-07 08:21:25 +0000380
danilchap162abd32015-12-10 02:39:40 -0800381 if we send
382 If the participant is a sender (we_sent true), the constant C is
383 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
384 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
385 number of senders.
niklase@google.com470e71d2011-07-07 08:21:25 +0000386
danilchap162abd32015-12-10 02:39:40 -0800387 if we receive only
388 If we_sent is not true, the constant C is set
389 to the average RTCP packet size divided by 75% of the RTCP
390 bandwidth. The constant n is set to the number of receivers
391 (members - senders). If the number of senders is greater than
392 25%, senders and receivers are treated together.
niklase@google.com470e71d2011-07-07 08:21:25 +0000393
danilchap162abd32015-12-10 02:39:40 -0800394 reconsideration NOT required for peer-to-peer
395 "timer reconsideration" is
396 employed. This algorithm implements a simple back-off mechanism
397 which causes users to hold back RTCP packet transmission if the
398 group sizes are increasing.
niklase@google.com470e71d2011-07-07 08:21:25 +0000399
danilchap162abd32015-12-10 02:39:40 -0800400 n = number of members
401 C = avg_size/(rtcpBW/4)
niklase@google.com470e71d2011-07-07 08:21:25 +0000402
danilchap162abd32015-12-10 02:39:40 -0800403 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
niklase@google.com470e71d2011-07-07 08:21:25 +0000404
danilchap162abd32015-12-10 02:39:40 -0800405 4. The calculated interval T is set to a number uniformly distributed
406 between 0.5 and 1.5 times the deterministic calculated interval.
niklase@google.com470e71d2011-07-07 08:21:25 +0000407
danilchap162abd32015-12-10 02:39:40 -0800408 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
409 for the fact that the timer reconsideration algorithm converges to
410 a value of the RTCP bandwidth below the intended average
411 */
niklase@google.com470e71d2011-07-07 08:21:25 +0000412
Erik Språng242e22b2015-05-11 10:17:43 +0200413 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000414
danilchap56036ff2016-03-22 11:14:09 -0700415 rtc::CritScope lock(&critical_section_rtcp_sender_);
xians@webrtc.org8738d272011-11-25 13:43:53 +0000416
pbosda903ea2015-10-02 02:36:56 -0700417 if (method_ == RtcpMode::kOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000418 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000419
Erik Språng242e22b2015-05-11 10:17:43 +0200420 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200421 // for video key-frames we want to send the RTCP before the large key-frame
422 // if we have a 100 ms margin
423 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
424 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000425
Erik Språng242e22b2015-05-11 10:17:43 +0200426 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200427 return true;
428 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200429 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200430 // wrap
431 return true;
432 }
433 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000434}
435
danilchap56036ff2016-03-22 11:14:09 -0700436std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSR(const RtcpContext& ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200437 // The timestamp of this RTCP packet should be estimated as the timestamp of
438 // the frame being captured at this moment. We are calculating that
439 // timestamp as the last frame's timestamp + the time since the last frame
440 // was captured.
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200441 uint32_t rtp_timestamp =
442 start_timestamp_ + last_rtp_timestamp_ +
443 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) *
Erik Språngf7c57762015-12-04 10:40:35 +0100444 (ctx.feedback_state_.frequency_hz / 1000);
niklase@google.com470e71d2011-07-07 08:21:25 +0000445
Erik Språngf7c57762015-12-04 10:40:35 +0100446 rtcp::SenderReport* report = new rtcp::SenderReport();
447 report->From(ssrc_);
danilchap34ed2b92016-01-18 02:43:32 -0800448 report->WithNtp(NtpTime(ctx.ntp_sec_, ctx.ntp_frac_));
Erik Språngf7c57762015-12-04 10:40:35 +0100449 report->WithRtpTimestamp(rtp_timestamp);
450 report->WithPacketCount(ctx.feedback_state_.packets_sent);
451 report->WithOctetCount(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_)
Erik Språngf7c57762015-12-04 10:40:35 +0100454 report->WithReportBlock(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();
henrikg91d6ede2015-09-17 00:24:34 -0700464 RTC_CHECK_LT(length_cname, static_cast<size_t>(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();
467 sdes->WithCName(ssrc_, cname_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200468
469 for (const auto it : csrc_cnames_)
Erik Språngf7c57762015-12-04 10:40:35 +0100470 sdes->WithCName(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();
477 report->From(ssrc_);
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200478 for (auto it : report_blocks_)
Erik Språngf7c57762015-12-04 10:40:35 +0100479 report->WithReportBlock(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();
487 pli->From(ssrc_);
488 pli->To(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) {
Erik Språngf7c57762015-12-04 10:40:35 +0100500 if (!ctx.repeat_)
sprang62dae192015-08-05 02:35:35 -0700501 ++sequence_number_fir_; // Do not increase if repetition.
niklase@google.com470e71d2011-07-07 08:21:25 +0000502
Erik Språngf7c57762015-12-04 10:40:35 +0100503 rtcp::Fir* fir = new rtcp::Fir();
504 fir->From(ssrc_);
Danil Chapovalov32e590e2016-01-22 11:04:56 +0100505 fir->WithRequestTo(remote_ssrc_, sequence_number_fir_);
Erik Språng242e22b2015-05-11 10:17:43 +0200506
507 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
508 "RTCPSender::FIR");
509 ++packet_type_counter_.fir_packets;
510 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
511 ssrc_, packet_type_counter_.fir_packets);
512
danilchap56036ff2016-03-22 11:14:09 -0700513 return std::unique_ptr<rtcp::RtcpPacket>(fir);
niklase@google.com470e71d2011-07-07 08:21:25 +0000514}
515
516/*
517 0 1 2 3
518 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
519 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
520 | First | Number | PictureID |
521 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
522*/
danilchap56036ff2016-03-22 11:14:09 -0700523std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSLI(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100524 rtcp::Sli* sli = new rtcp::Sli();
525 sli->From(ssrc_);
526 sli->To(remote_ssrc_);
sprang0365a272015-08-11 01:02:37 -0700527 // Crop picture id to 6 least significant bits.
Erik Språngf7c57762015-12-04 10:40:35 +0100528 sli->WithPictureId(ctx.picture_id_ & 0x3F);
sprang0365a272015-08-11 01:02:37 -0700529
danilchap56036ff2016-03-22 11:14:09 -0700530 return std::unique_ptr<rtcp::RtcpPacket>(sli);
niklase@google.com470e71d2011-07-07 08:21:25 +0000531}
532
533/*
534 0 1 2 3
535 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
536 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
537 | PB |0| Payload Type| Native RPSI bit string |
538 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
539 | defined per codec ... | Padding (0) |
540 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
541*/
542/*
543* Note: not generic made for VP8
544*/
danilchap56036ff2016-03-22 11:14:09 -0700545std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildRPSI(
Erik Språngf7c57762015-12-04 10:40:35 +0100546 const RtcpContext& ctx) {
547 if (ctx.feedback_state_.send_payload_type == 0xFF)
548 return nullptr;
Erik Språng242e22b2015-05-11 10:17:43 +0200549
Erik Språngf7c57762015-12-04 10:40:35 +0100550 rtcp::Rpsi* rpsi = new rtcp::Rpsi();
551 rpsi->From(ssrc_);
552 rpsi->To(remote_ssrc_);
553 rpsi->WithPayloadType(ctx.feedback_state_.send_payload_type);
554 rpsi->WithPictureId(ctx.picture_id_);
sprangcf7f54d2015-08-13 04:37:42 -0700555
danilchap56036ff2016-03-22 11:14:09 -0700556 return std::unique_ptr<rtcp::RtcpPacket>(rpsi);
niklase@google.com470e71d2011-07-07 08:21:25 +0000557}
558
danilchap56036ff2016-03-22 11:14:09 -0700559std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildREMB(
Erik Språngf7c57762015-12-04 10:40:35 +0100560 const RtcpContext& ctx) {
561 rtcp::Remb* remb = new rtcp::Remb();
562 remb->From(ssrc_);
sprangdd4edc52015-08-21 04:21:51 -0700563 for (uint32_t ssrc : remb_ssrcs_)
Erik Språngf7c57762015-12-04 10:40:35 +0100564 remb->AppliesTo(ssrc);
565 remb->WithBitrateBps(remb_bitrate_);
Erik Språng61be2a42015-04-27 13:32:52 +0200566
Erik Språng242e22b2015-05-11 10:17:43 +0200567 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
568 "RTCPSender::REMB");
569
danilchap56036ff2016-03-22 11:14:09 -0700570 return std::unique_ptr<rtcp::RtcpPacket>(remb);
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000571}
572
Erik Språng61be2a42015-04-27 13:32:52 +0200573void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
danilchap56036ff2016-03-22 11:14:09 -0700574 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200575 tmmbr_send_ = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000576}
577
danilchap56036ff2016-03-22 11:14:09 -0700578std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBR(
Erik Språngf7c57762015-12-04 10:40:35 +0100579 const RtcpContext& ctx) {
580 if (ctx.feedback_state_.module == nullptr)
581 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200582 // Before sending the TMMBR check the received TMMBN, only an owner is
583 // allowed to raise the bitrate:
584 // * If the sender is an owner of the TMMBN -> send TMMBR
585 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000586
Erik Språng61be2a42015-04-27 13:32:52 +0200587 // get current bounding set from RTCP receiver
588 bool tmmbrOwner = false;
589 // store in candidateSet, allocates one extra slot
Erik Språng242e22b2015-05-11 10:17:43 +0200590 TMMBRSet* candidateSet = tmmbr_help_.CandidateSet();
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
595 int32_t lengthOfBoundingSet =
danilchap6db6cdc2015-12-15 02:54:47 -0800596 ctx.feedback_state_.module->BoundingSet(&tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +0000597
Erik Språng61be2a42015-04-27 13:32:52 +0200598 if (lengthOfBoundingSet > 0) {
599 for (int32_t i = 0; i < lengthOfBoundingSet; i++) {
Erik Språng242e22b2015-05-11 10:17:43 +0200600 if (candidateSet->Tmmbr(i) == tmmbr_send_ &&
601 candidateSet->PacketOH(i) == 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 }
Erik Språng61be2a42015-04-27 13:32:52 +0200606 if (!tmmbrOwner) {
607 // use received bounding set as candidate set
608 // add current tuple
Erik Språng242e22b2015-05-11 10:17:43 +0200609 candidateSet->SetEntry(lengthOfBoundingSet, tmmbr_send_, packet_oh_send_,
610 ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200611 int numCandidates = lengthOfBoundingSet + 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000612
Erik Språng61be2a42015-04-27 13:32:52 +0200613 // find bounding set
Erik Språngf7c57762015-12-04 10:40:35 +0100614 TMMBRSet* boundingSet = nullptr;
Erik Språng242e22b2015-05-11 10:17:43 +0200615 int numBoundingSet = tmmbr_help_.FindTMMBRBoundingSet(boundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200616 if (numBoundingSet > 0 || numBoundingSet <= numCandidates)
Erik Språng242e22b2015-05-11 10:17:43 +0200617 tmmbrOwner = tmmbr_help_.IsOwner(ssrc_, numBoundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200618 if (!tmmbrOwner) {
Erik Språngf7c57762015-12-04 10:40:35 +0100619 // Did not enter bounding set, no meaning to send this request.
620 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200621 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000622 }
Erik Språng61be2a42015-04-27 13:32:52 +0200623 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000624
Erik Språngf7c57762015-12-04 10:40:35 +0100625 if (!tmmbr_send_)
626 return nullptr;
sprang81a3e602015-08-21 05:30:11 -0700627
Erik Språngf7c57762015-12-04 10:40:35 +0100628 rtcp::Tmmbr* tmmbr = new rtcp::Tmmbr();
629 tmmbr->From(ssrc_);
danilchapf174e3a2016-02-05 04:56:36 -0800630 rtcp::TmmbItem request;
631 request.set_ssrc(remote_ssrc_);
632 request.set_bitrate_bps(tmmbr_send_ * 1000);
633 request.set_packet_overhead(packet_oh_send_);
634 tmmbr->WithTmmbr(request);
Erik Språngf7c57762015-12-04 10:40:35 +0100635
danilchap56036ff2016-03-22 11:14:09 -0700636 return std::unique_ptr<rtcp::RtcpPacket>(tmmbr);
Erik Språng61be2a42015-04-27 13:32:52 +0200637}
638
danilchap56036ff2016-03-22 11:14:09 -0700639std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBN(
Erik Språngf7c57762015-12-04 10:40:35 +0100640 const RtcpContext& ctx) {
Erik Språng242e22b2015-05-11 10:17:43 +0200641 TMMBRSet* boundingSet = tmmbr_help_.BoundingSetToSend();
Erik Språngf7c57762015-12-04 10:40:35 +0100642 if (boundingSet == nullptr)
643 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200644
Erik Språngf7c57762015-12-04 10:40:35 +0100645 rtcp::Tmmbn* tmmbn = new rtcp::Tmmbn();
646 tmmbn->From(ssrc_);
sprangd83df502015-08-27 01:05:08 -0700647 for (uint32_t i = 0; i < boundingSet->lengthOfSet(); i++) {
648 if (boundingSet->Tmmbr(i) > 0) {
Erik Språngf7c57762015-12-04 10:40:35 +0100649 tmmbn->WithTmmbr(boundingSet->Ssrc(i), boundingSet->Tmmbr(i),
650 boundingSet->PacketOH(i));
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000651 }
Erik Språng61be2a42015-04-27 13:32:52 +0200652 }
sprangd83df502015-08-27 01:05:08 -0700653
danilchap56036ff2016-03-22 11:14:09 -0700654 return std::unique_ptr<rtcp::RtcpPacket>(tmmbn);
niklase@google.com470e71d2011-07-07 08:21:25 +0000655}
656
danilchap56036ff2016-03-22 11:14:09 -0700657std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildAPP(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100658 rtcp::App* app = new rtcp::App();
659 app->From(ssrc_);
660 app->WithSubType(app_sub_type_);
661 app->WithName(app_name_);
662 app->WithData(app_data_.get(), app_length_);
Erik Språng521875a2015-09-01 10:11:16 +0200663
danilchap56036ff2016-03-22 11:14:09 -0700664 return std::unique_ptr<rtcp::RtcpPacket>(app);
Erik Språng61be2a42015-04-27 13:32:52 +0200665}
666
danilchap56036ff2016-03-22 11:14:09 -0700667std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildNACK(
Erik Språngf7c57762015-12-04 10:40:35 +0100668 const RtcpContext& ctx) {
669 rtcp::Nack* nack = new rtcp::Nack();
670 nack->From(ssrc_);
671 nack->To(remote_ssrc_);
672 nack->WithList(ctx.nack_list_, ctx.nack_size_);
Erik Språng61be2a42015-04-27 13:32:52 +0200673
674 // Report stats.
675 NACKStringBuilder stringBuilder;
Erik Språngf7c57762015-12-04 10:40:35 +0100676 for (int idx = 0; idx < ctx.nack_size_; ++idx) {
677 stringBuilder.PushNACK(ctx.nack_list_[idx]);
678 nack_stats_.ReportRequest(ctx.nack_list_[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +0200679 }
Erik Språng61be2a42015-04-27 13:32:52 +0200680 packet_type_counter_.nack_requests = nack_stats_.requests();
681 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +0200682
683 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
684 "RTCPSender::NACK", "nacks",
685 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
686 ++packet_type_counter_.nack_packets;
687 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
688 ssrc_, packet_type_counter_.nack_packets);
689
danilchap56036ff2016-03-22 11:14:09 -0700690 return std::unique_ptr<rtcp::RtcpPacket>(nack);
Erik Språng61be2a42015-04-27 13:32:52 +0200691}
692
danilchap56036ff2016-03-22 11:14:09 -0700693std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildBYE(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100694 rtcp::Bye* bye = new rtcp::Bye();
695 bye->From(ssrc_);
sprangd8ee4f92015-08-24 03:25:19 -0700696 for (uint32_t csrc : csrcs_)
Erik Språngf7c57762015-12-04 10:40:35 +0100697 bye->WithCsrc(csrc);
sprangd8ee4f92015-08-24 03:25:19 -0700698
danilchap56036ff2016-03-22 11:14:09 -0700699 return std::unique_ptr<rtcp::RtcpPacket>(bye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000700}
701
danilchap56036ff2016-03-22 11:14:09 -0700702std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildReceiverReferenceTime(
Erik Språngf7c57762015-12-04 10:40:35 +0100703 const RtcpContext& ctx) {
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000704
Danil Chapovalov256e5b22016-01-15 14:16:24 +0100705 rtcp::ExtendedReports* xr = new rtcp::ExtendedReports();
Erik Språngf7c57762015-12-04 10:40:35 +0100706 xr->From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000707
Erik Språngca28fdc2015-08-31 14:00:50 +0200708 rtcp::Rrtr rrtr;
Danil Chapovalovfc47ed62015-12-07 14:46:35 +0100709 rrtr.WithNtp(NtpTime(ctx.ntp_sec_, ctx.ntp_frac_));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000710
danilchapde138822016-01-29 11:26:14 -0800711 xr->WithRrtr(rrtr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000712
Erik Språngca28fdc2015-08-31 14:00:50 +0200713 // TODO(sprang): Merge XR report sending to contain all of RRTR, DLRR, VOIP?
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000714
danilchap56036ff2016-03-22 11:14:09 -0700715 return std::unique_ptr<rtcp::RtcpPacket>(xr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000716}
717
danilchap56036ff2016-03-22 11:14:09 -0700718std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildDlrr(
Erik Språngf7c57762015-12-04 10:40:35 +0100719 const RtcpContext& ctx) {
Danil Chapovalov256e5b22016-01-15 14:16:24 +0100720 rtcp::ExtendedReports* xr = new rtcp::ExtendedReports();
Erik Språngf7c57762015-12-04 10:40:35 +0100721 xr->From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000722
Erik Språngca28fdc2015-08-31 14:00:50 +0200723 rtcp::Dlrr dlrr;
Erik Språngf7c57762015-12-04 10:40:35 +0100724 const RtcpReceiveTimeInfo& info = ctx.feedback_state_.last_xr_rr;
Erik Språngca28fdc2015-08-31 14:00:50 +0200725 dlrr.WithDlrrItem(info.sourceSSRC, info.lastRR, info.delaySinceLastRR);
726
danilchapde138822016-01-29 11:26:14 -0800727 xr->WithDlrr(dlrr);
Erik Språngca28fdc2015-08-31 14:00:50 +0200728
danilchap56036ff2016-03-22 11:14:09 -0700729 return std::unique_ptr<rtcp::RtcpPacket>(xr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000730}
731
Erik Språng242e22b2015-05-11 10:17:43 +0200732// TODO(sprang): Add a unit test for this, or remove if the code isn't used.
danilchap56036ff2016-03-22 11:14:09 -0700733std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildVoIPMetric(
Erik Språngf7c57762015-12-04 10:40:35 +0100734 const RtcpContext& context) {
Danil Chapovalov256e5b22016-01-15 14:16:24 +0100735 rtcp::ExtendedReports* xr = new rtcp::ExtendedReports();
Erik Språngf7c57762015-12-04 10:40:35 +0100736 xr->From(ssrc_);
Erik Språngca28fdc2015-08-31 14:00:50 +0200737
738 rtcp::VoipMetric voip;
739 voip.To(remote_ssrc_);
danilchap91941ae2015-12-15 07:06:36 -0800740 voip.WithVoipMetric(xr_voip_metric_);
Erik Språngca28fdc2015-08-31 14:00:50 +0200741
danilchapde138822016-01-29 11:26:14 -0800742 xr->WithVoipMetric(voip);
Erik Språngca28fdc2015-08-31 14:00:50 +0200743
danilchap56036ff2016-03-22 11:14:09 -0700744 return std::unique_ptr<rtcp::RtcpPacket>(xr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000745}
746
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000747int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200748 RTCPPacketType packetType,
749 int32_t nack_size,
750 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000751 bool repeat,
752 uint64_t pictureID) {
Erik Språng242e22b2015-05-11 10:17:43 +0200753 return SendCompoundRTCP(
754 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
755 nack_size, nack_list, repeat, pictureID);
756}
757
758int32_t RTCPSender::SendCompoundRTCP(
759 const FeedbackState& feedback_state,
Erik Språngf7c57762015-12-04 10:40:35 +0100760 const std::set<RTCPPacketType>& packet_types,
Erik Språng242e22b2015-05-11 10:17:43 +0200761 int32_t nack_size,
762 const uint16_t* nack_list,
763 bool repeat,
764 uint64_t pictureID) {
terelius429c3452016-01-21 05:42:04 -0800765 PacketContainer container(transport_, event_log_);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000766 {
danilchap56036ff2016-03-22 11:14:09 -0700767 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbosda903ea2015-10-02 02:36:56 -0700768 if (method_ == RtcpMode::kOff) {
Erik Språng61be2a42015-04-27 13:32:52 +0200769 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
770 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +0000771 }
Erik Språngf7c57762015-12-04 10:40:35 +0100772
773 // We need to send our NTP even if we haven't received any reports.
774 uint32_t ntp_sec;
775 uint32_t ntp_frac;
776 clock_->CurrentNtp(ntp_sec, ntp_frac);
777 RtcpContext context(feedback_state, nack_size, nack_list, repeat, pictureID,
danilchap56036ff2016-03-22 11:14:09 -0700778 ntp_sec, ntp_frac);
Erik Språngf7c57762015-12-04 10:40:35 +0100779
780 PrepareReport(packet_types, feedback_state);
781
danilchap56036ff2016-03-22 11:14:09 -0700782 std::unique_ptr<rtcp::RtcpPacket> packet_bye;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800783
Erik Språngf7c57762015-12-04 10:40:35 +0100784 auto it = report_flags_.begin();
785 while (it != report_flags_.end()) {
786 auto builder_it = builders_.find(it->type);
787 RTC_DCHECK(builder_it != builders_.end());
788 if (it->is_volatile) {
789 report_flags_.erase(it++);
790 } else {
791 ++it;
792 }
793
794 BuilderFunc func = builder_it->second;
danilchap56036ff2016-03-22 11:14:09 -0700795 std::unique_ptr<rtcp::RtcpPacket> packet = (this->*func)(context);
Erik Språngf7c57762015-12-04 10:40:35 +0100796 if (packet.get() == nullptr)
797 return -1;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800798 // If there is a BYE, don't append now - save it and append it
799 // at the end later.
800 if (builder_it->first == kRtcpBye) {
801 packet_bye = std::move(packet);
802 } else {
803 container.Append(packet.release());
804 }
805 }
806
807 // Append the BYE now at the end
808 if (packet_bye) {
809 container.Append(packet_bye.release());
Erik Språngf7c57762015-12-04 10:40:35 +0100810 }
811
812 if (packet_type_counter_observer_ != nullptr) {
813 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
814 remote_ssrc_, packet_type_counter_);
815 }
816
817 RTC_DCHECK(AllVolatileFlagsConsumed());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000818 }
Erik Språng61be2a42015-04-27 13:32:52 +0200819
danilchap41befce2016-03-30 11:11:51 -0700820 size_t bytes_sent = container.SendPackets(max_payload_length_);
Erik Språngf7c57762015-12-04 10:40:35 +0100821 return bytes_sent == 0 ? -1 : 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000822}
823
Erik Språngf7c57762015-12-04 10:40:35 +0100824void RTCPSender::PrepareReport(const std::set<RTCPPacketType>& packetTypes,
825 const FeedbackState& feedback_state) {
Erik Språng242e22b2015-05-11 10:17:43 +0200826 // Add all flags as volatile. Non volatile entries will not be overwritten
827 // and all new volatile flags added will be consumed by the end of this call.
828 SetFlags(packetTypes, true);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000829
Erik Språng61be2a42015-04-27 13:32:52 +0200830 if (packet_type_counter_.first_packet_time_ms == -1)
Erik Språng242e22b2015-05-11 10:17:43 +0200831 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språng61be2a42015-04-27 13:32:52 +0200832
Erik Språng242e22b2015-05-11 10:17:43 +0200833 bool generate_report;
834 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
835 // Report type already explicitly set, don't automatically populate.
836 generate_report = true;
henrikg91d6ede2015-09-17 00:24:34 -0700837 RTC_DCHECK(ConsumeFlag(kRtcpReport) == false);
Erik Språng242e22b2015-05-11 10:17:43 +0200838 } else {
839 generate_report =
pbosda903ea2015-10-02 02:36:56 -0700840 (ConsumeFlag(kRtcpReport) && method_ == RtcpMode::kReducedSize) ||
841 method_ == RtcpMode::kCompound;
Erik Språng242e22b2015-05-11 10:17:43 +0200842 if (generate_report)
843 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000844 }
845
Erik Språng0ea42d32015-06-25 14:46:16 +0200846 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
Erik Språng242e22b2015-05-11 10:17:43 +0200847 SetFlag(kRtcpSdes, true);
848
Erik Språng242e22b2015-05-11 10:17:43 +0200849 if (generate_report) {
850 if (!sending_ && xr_send_receiver_reference_time_enabled_)
851 SetFlag(kRtcpXrReceiverReferenceTime, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200852 if (feedback_state.has_last_xr_rr)
Erik Språng242e22b2015-05-11 10:17:43 +0200853 SetFlag(kRtcpXrDlrrReportBlock, true);
854
855 // generate next time to send an RTCP report
danilchap47a740b2015-12-15 00:30:07 -0800856 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000857
danilchap47a740b2015-12-15 00:30:07 -0800858 if (!audio_) {
Erik Språng242e22b2015-05-11 10:17:43 +0200859 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200860 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
861 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
862 if (send_bitrate_kbit != 0)
863 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000864 }
Erik Språng61be2a42015-04-27 13:32:52 +0200865 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
866 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
Erik Språng61be2a42015-04-27 13:32:52 +0200867 }
danilchap47a740b2015-12-15 00:30:07 -0800868 // The interval between RTCP packets is varied randomly over the
869 // range [1/2,3/2] times the calculated interval.
870 uint32_t timeToNext =
871 random_.Rand(minIntervalMs * 1 / 2, minIntervalMs * 3 / 2);
Erik Språng242e22b2015-05-11 10:17:43 +0200872 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000873
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000874 StatisticianMap statisticians =
875 receive_statistics_->GetActiveStatisticians();
danilchapa72e7342015-12-22 08:07:45 -0800876 RTC_DCHECK(report_blocks_.empty());
877 for (auto& it : statisticians) {
878 AddReportBlock(feedback_state, it.first, it.second);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000879 }
880 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000881}
882
danilchapa72e7342015-12-22 08:07:45 -0800883bool RTCPSender::AddReportBlock(const FeedbackState& feedback_state,
884 uint32_t ssrc,
885 StreamStatistician* statistician) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000886 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000887 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000888 if (!statistician->GetStatistics(&stats, true))
889 return false;
danilchapa72e7342015-12-22 08:07:45 -0800890
891 if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) {
892 LOG(LS_WARNING) << "Too many report blocks.";
893 return false;
894 }
895 RTC_DCHECK(report_blocks_.find(ssrc) == report_blocks_.end());
896 rtcp::ReportBlock* block = &report_blocks_[ssrc];
897 block->To(ssrc);
898 block->WithFractionLost(stats.fraction_lost);
899 if (!block->WithCumulativeLost(stats.cumulative_lost)) {
900 report_blocks_.erase(ssrc);
901 LOG(LS_WARNING) << "Cumulative lost is oversized.";
902 return false;
903 }
904 block->WithExtHighestSeqNum(stats.extended_max_sequence_number);
905 block->WithJitter(stats.jitter);
906 block->WithLastSr(feedback_state.remote_sr);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000907
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200908 // TODO(sprang): Do we really need separate time stamps for each report?
909 // Get our NTP as late as possible to avoid a race.
910 uint32_t ntp_secs;
911 uint32_t ntp_frac;
912 clock_->CurrentNtp(ntp_secs, ntp_frac);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000913
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200914 // Delay since last received report.
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000915 if ((feedback_state.last_rr_ntp_secs != 0) ||
916 (feedback_state.last_rr_ntp_frac != 0)) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200917 // Get the 16 lowest bits of seconds and the 16 highest bits of fractions.
918 uint32_t now = ntp_secs & 0x0000FFFF;
Erik Språng61be2a42015-04-27 13:32:52 +0200919 now <<= 16;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200920 now += (ntp_frac & 0xffff0000) >> 16;
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
danilchapa72e7342015-12-22 08:07:45 -0800926 block->WithDelayLastSr(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) {
danilchap56036ff2016-03-22 11:14:09 -0700932 RTC_DCHECK_LE(csrcs.size(), static_cast<size_t>(kRtpCsrcSize));
933 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
Erik Språng61be2a42015-04-27 13:32:52 +0200956int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
danilchap56036ff2016-03-22 11:14:09 -0700957 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200958 memcpy(&xr_voip_metric_, VoIPMetric, sizeof(RTCPVoIPMetric));
niklase@google.com470e71d2011-07-07 08:21:25 +0000959
Erik Språng242e22b2015-05-11 10:17:43 +0200960 SetFlag(kRtcpXrVoipMetric, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200961 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000962}
963
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000964void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700965 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200966 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000967}
968
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000969bool RTCPSender::RtcpXrReceiverReferenceTime() const {
danilchap56036ff2016-03-22 11:14:09 -0700970 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200971 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000972}
973
niklase@google.com470e71d2011-07-07 08:21:25 +0000974// no callbacks allowed inside this function
Peter Boström9d0c4322016-02-16 17:59:27 +0100975int32_t RTCPSender::SetTMMBN(const TMMBRSet* boundingSet) {
danilchap56036ff2016-03-22 11:14:09 -0700976 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000977
Peter Boström9d0c4322016-02-16 17:59:27 +0100978 if (0 == tmmbr_help_.SetTMMBRBoundingSetToSend(boundingSet)) {
Erik Språng242e22b2015-05-11 10:17:43 +0200979 SetFlag(kRtcpTmmbn, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200980 return 0;
981 }
982 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000983}
Erik Språng61be2a42015-04-27 13:32:52 +0200984
Erik Språng242e22b2015-05-11 10:17:43 +0200985void RTCPSender::SetFlag(RTCPPacketType type, bool is_volatile) {
986 report_flags_.insert(ReportFlag(type, is_volatile));
987}
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
995bool RTCPSender::IsFlagPresent(RTCPPacketType type) const {
996 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
997}
998
999bool RTCPSender::ConsumeFlag(RTCPPacketType type, bool forced) {
1000 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
sprang233bd872015-09-08 13:25:16 -07001016bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
sprang233bd872015-09-08 13:25:16 -07001017 class Sender : public rtcp::RtcpPacket::PacketReadyCallback {
1018 public:
terelius429c3452016-01-21 05:42:04 -08001019 Sender(Transport* transport, RtcEventLog* event_log)
1020 : transport_(transport), event_log_(event_log), send_failure_(false) {}
sprang233bd872015-09-08 13:25:16 -07001021
1022 void OnPacketReady(uint8_t* data, size_t length) override {
terelius429c3452016-01-21 05:42:04 -08001023 if (transport_->SendRtcp(data, length)) {
1024 if (event_log_) {
1025 event_log_->LogRtcpPacket(kOutgoingPacket, MediaType::ANY, data,
1026 length);
1027 }
1028 } else {
sprang233bd872015-09-08 13:25:16 -07001029 send_failure_ = true;
terelius429c3452016-01-21 05:42:04 -08001030 }
sprang233bd872015-09-08 13:25:16 -07001031 }
1032
1033 Transport* const transport_;
terelius429c3452016-01-21 05:42:04 -08001034 RtcEventLog* const event_log_;
sprang233bd872015-09-08 13:25:16 -07001035 bool send_failure_;
terelius429c3452016-01-21 05:42:04 -08001036 // TODO(terelius): We would like to
1037 // RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(Sender);
1038 // but we can't because of an incorrect warning (C4822) in MVS 2013.
1039 } sender(transport_, event_log_);
sprang233bd872015-09-08 13:25:16 -07001040
danilchap41befce2016-03-30 11:11:51 -07001041 RTC_DCHECK_LE(max_payload_length_, static_cast<size_t>(IP_PACKET_SIZE));
sprang233bd872015-09-08 13:25:16 -07001042 uint8_t buffer[IP_PACKET_SIZE];
danilchap41befce2016-03-30 11:11:51 -07001043 return packet.BuildExternalBuffer(buffer, max_payload_length_, &sender) &&
sprang233bd872015-09-08 13:25:16 -07001044 !sender.send_failure_;
1045}
1046
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001047} // namespace webrtc