blob: 440bd50d57461a91b4e9105e9ea1629cd9bd16d2 [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
pbosda903ea2015-10-02 02:36:56 -0700211void RTCPSender::SetRTCPStatus(RtcpMode method) {
danilchap56036ff2016-03-22 11:14:09 -0700212 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200213 method_ = method;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000214
pbosda903ea2015-10-02 02:36:56 -0700215 if (method == RtcpMode::kOff)
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000216 return;
Erik Språng242e22b2015-05-11 10:17:43 +0200217 next_time_to_send_rtcp_ =
218 clock_->TimeInMilliseconds() +
219 (audio_ ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000220}
221
Erik Språng61be2a42015-04-27 13:32:52 +0200222bool RTCPSender::Sending() const {
danilchap56036ff2016-03-22 11:14:09 -0700223 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200224 return sending_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000225}
226
Erik Språng61be2a42015-04-27 13:32:52 +0200227int32_t RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
228 bool sending) {
229 bool sendRTCPBye = false;
230 {
danilchap56036ff2016-03-22 11:14:09 -0700231 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000232
pbosda903ea2015-10-02 02:36:56 -0700233 if (method_ != RtcpMode::kOff) {
Erik Språng242e22b2015-05-11 10:17:43 +0200234 if (sending == false && sending_ == true) {
Erik Språng61be2a42015-04-27 13:32:52 +0200235 // Trigger RTCP bye
236 sendRTCPBye = true;
237 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000238 }
Erik Språng242e22b2015-05-11 10:17:43 +0200239 sending_ = sending;
Erik Språng61be2a42015-04-27 13:32:52 +0200240 }
241 if (sendRTCPBye)
242 return SendRTCP(feedback_state, kRtcpBye);
243 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000244}
245
Erik Språng61be2a42015-04-27 13:32:52 +0200246bool RTCPSender::REMB() const {
danilchap56036ff2016-03-22 11:14:09 -0700247 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200248 return remb_enabled_;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000249}
250
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000251void RTCPSender::SetREMBStatus(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700252 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200253 remb_enabled_ = enable;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000254}
255
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000256void RTCPSender::SetREMBData(uint32_t bitrate,
257 const std::vector<uint32_t>& ssrcs) {
danilchap56036ff2016-03-22 11:14:09 -0700258 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200259 remb_bitrate_ = bitrate;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000260 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000261
Erik Språng242e22b2015-05-11 10:17:43 +0200262 if (remb_enabled_)
263 SetFlag(kRtcpRemb, false);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000264 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
265 // throttled by the caller.
Erik Språng242e22b2015-05-11 10:17:43 +0200266 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000267}
268
Erik Språng61be2a42015-04-27 13:32:52 +0200269bool RTCPSender::TMMBR() const {
danilchap56036ff2016-03-22 11:14:09 -0700270 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200271 return IsFlagPresent(RTCPPacketType::kRtcpTmmbr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000272}
273
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000274void RTCPSender::SetTMMBRStatus(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700275 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200276 if (enable) {
277 SetFlag(RTCPPacketType::kRtcpTmmbr, false);
278 } else {
279 ConsumeFlag(RTCPPacketType::kRtcpTmmbr, true);
280 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000281}
282
danilchap41befce2016-03-30 11:11:51 -0700283void RTCPSender::SetMaxPayloadLength(size_t max_payload_length) {
284 max_payload_length_ = max_payload_length;
285}
286
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000287void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
danilchap56036ff2016-03-22 11:14:09 -0700288 rtc::CritScope lock(&critical_section_rtcp_sender_);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000289 start_timestamp_ = start_timestamp;
290}
291
292void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
293 int64_t capture_time_ms) {
danilchap56036ff2016-03-22 11:14:09 -0700294 rtc::CritScope lock(&critical_section_rtcp_sender_);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000295 last_rtp_timestamp_ = rtp_timestamp;
296 if (capture_time_ms < 0) {
297 // We don't currently get a capture time from VoiceEngine.
Erik Språng242e22b2015-05-11 10:17:43 +0200298 last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000299 } else {
300 last_frame_capture_time_ms_ = capture_time_ms;
301 }
302}
303
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000304void RTCPSender::SetSSRC(uint32_t ssrc) {
danilchap56036ff2016-03-22 11:14:09 -0700305 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000306
Erik Språng242e22b2015-05-11 10:17:43 +0200307 if (ssrc_ != 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200308 // not first SetSSRC, probably due to a collision
309 // schedule a new RTCP report
310 // make sure that we send a RTP packet
Erik Språng242e22b2015-05-11 10:17:43 +0200311 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
Erik Språng61be2a42015-04-27 13:32:52 +0200312 }
Erik Språng242e22b2015-05-11 10:17:43 +0200313 ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000314}
315
Erik Språng61be2a42015-04-27 13:32:52 +0200316void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
danilchap56036ff2016-03-22 11:14:09 -0700317 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200318 remote_ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000319}
320
Peter Boström9ba52f82015-06-01 14:12:28 +0200321int32_t RTCPSender::SetCNAME(const char* c_name) {
322 if (!c_name)
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000323 return -1;
324
henrikg91d6ede2015-09-17 00:24:34 -0700325 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
danilchap56036ff2016-03-22 11:14:09 -0700326 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200327 cname_ = c_name;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000328 return 0;
329}
330
Erik Språng0ea42d32015-06-25 14:46:16 +0200331int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC, const char* c_name) {
danilchap56036ff2016-03-22 11:14:09 -0700332 RTC_DCHECK(c_name);
henrikg91d6ede2015-09-17 00:24:34 -0700333 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
danilchap56036ff2016-03-22 11:14:09 -0700334 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200335 if (csrc_cnames_.size() >= kRtpCsrcSize)
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000336 return -1;
Erik Språng0ea42d32015-06-25 14:46:16 +0200337
338 csrc_cnames_[SSRC] = c_name;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000339 return 0;
340}
341
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000342int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
danilchap56036ff2016-03-22 11:14:09 -0700343 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200344 auto it = csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000345
Erik Språng242e22b2015-05-11 10:17:43 +0200346 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000347 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200348
Erik Språng242e22b2015-05-11 10:17:43 +0200349 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000350 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000351}
352
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000353bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
danilchap162abd32015-12-10 02:39:40 -0800354 /*
355 For audio we use a fix 5 sec interval
niklase@google.com470e71d2011-07-07 08:21:25 +0000356
danilchap162abd32015-12-10 02:39:40 -0800357 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
358 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
359 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000360
361
danilchap162abd32015-12-10 02:39:40 -0800362 From RFC 3550
niklase@google.com470e71d2011-07-07 08:21:25 +0000363
danilchap162abd32015-12-10 02:39:40 -0800364 MAX RTCP BW is 5% if the session BW
365 A send report is approximately 65 bytes inc CNAME
366 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000367
danilchap162abd32015-12-10 02:39:40 -0800368 The RECOMMENDED value for the reduced minimum in seconds is 360
369 divided by the session bandwidth in kilobits/second. This minimum
370 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
niklase@google.com470e71d2011-07-07 08:21:25 +0000371
danilchap162abd32015-12-10 02:39:40 -0800372 If the participant has not yet sent an RTCP packet (the variable
373 initial is true), the constant Tmin is set to 2.5 seconds, else it
374 is set to 5 seconds.
niklase@google.com470e71d2011-07-07 08:21:25 +0000375
danilchap162abd32015-12-10 02:39:40 -0800376 The interval between RTCP packets is varied randomly over the
377 range [0.5,1.5] times the calculated interval to avoid unintended
378 synchronization of all participants
niklase@google.com470e71d2011-07-07 08:21:25 +0000379
danilchap162abd32015-12-10 02:39:40 -0800380 if we send
381 If the participant is a sender (we_sent true), the constant C is
382 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
383 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
384 number of senders.
niklase@google.com470e71d2011-07-07 08:21:25 +0000385
danilchap162abd32015-12-10 02:39:40 -0800386 if we receive only
387 If we_sent is not true, the constant C is set
388 to the average RTCP packet size divided by 75% of the RTCP
389 bandwidth. The constant n is set to the number of receivers
390 (members - senders). If the number of senders is greater than
391 25%, senders and receivers are treated together.
niklase@google.com470e71d2011-07-07 08:21:25 +0000392
danilchap162abd32015-12-10 02:39:40 -0800393 reconsideration NOT required for peer-to-peer
394 "timer reconsideration" is
395 employed. This algorithm implements a simple back-off mechanism
396 which causes users to hold back RTCP packet transmission if the
397 group sizes are increasing.
niklase@google.com470e71d2011-07-07 08:21:25 +0000398
danilchap162abd32015-12-10 02:39:40 -0800399 n = number of members
400 C = avg_size/(rtcpBW/4)
niklase@google.com470e71d2011-07-07 08:21:25 +0000401
danilchap162abd32015-12-10 02:39:40 -0800402 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
niklase@google.com470e71d2011-07-07 08:21:25 +0000403
danilchap162abd32015-12-10 02:39:40 -0800404 4. The calculated interval T is set to a number uniformly distributed
405 between 0.5 and 1.5 times the deterministic calculated interval.
niklase@google.com470e71d2011-07-07 08:21:25 +0000406
danilchap162abd32015-12-10 02:39:40 -0800407 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
408 for the fact that the timer reconsideration algorithm converges to
409 a value of the RTCP bandwidth below the intended average
410 */
niklase@google.com470e71d2011-07-07 08:21:25 +0000411
Erik Språng242e22b2015-05-11 10:17:43 +0200412 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000413
danilchap56036ff2016-03-22 11:14:09 -0700414 rtc::CritScope lock(&critical_section_rtcp_sender_);
xians@webrtc.org8738d272011-11-25 13:43:53 +0000415
pbosda903ea2015-10-02 02:36:56 -0700416 if (method_ == RtcpMode::kOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000417 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000418
Erik Språng242e22b2015-05-11 10:17:43 +0200419 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200420 // for video key-frames we want to send the RTCP before the large key-frame
421 // if we have a 100 ms margin
422 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
423 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000424
Erik Språng242e22b2015-05-11 10:17:43 +0200425 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200426 return true;
427 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200428 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200429 // wrap
430 return true;
431 }
432 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000433}
434
danilchap56036ff2016-03-22 11:14:09 -0700435std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSR(const RtcpContext& ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200436 // The timestamp of this RTCP packet should be estimated as the timestamp of
437 // the frame being captured at this moment. We are calculating that
438 // timestamp as the last frame's timestamp + the time since the last frame
439 // was captured.
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200440 uint32_t rtp_timestamp =
441 start_timestamp_ + last_rtp_timestamp_ +
442 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) *
Erik Språngf7c57762015-12-04 10:40:35 +0100443 (ctx.feedback_state_.frequency_hz / 1000);
niklase@google.com470e71d2011-07-07 08:21:25 +0000444
Erik Språngf7c57762015-12-04 10:40:35 +0100445 rtcp::SenderReport* report = new rtcp::SenderReport();
446 report->From(ssrc_);
danilchap34ed2b92016-01-18 02:43:32 -0800447 report->WithNtp(NtpTime(ctx.ntp_sec_, ctx.ntp_frac_));
Erik Språngf7c57762015-12-04 10:40:35 +0100448 report->WithRtpTimestamp(rtp_timestamp);
449 report->WithPacketCount(ctx.feedback_state_.packets_sent);
450 report->WithOctetCount(ctx.feedback_state_.media_bytes_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000451
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200452 for (auto it : report_blocks_)
Erik Språngf7c57762015-12-04 10:40:35 +0100453 report->WithReportBlock(it.second);
niklase@google.com470e71d2011-07-07 08:21:25 +0000454
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200455 report_blocks_.clear();
Erik Språngf7c57762015-12-04 10:40:35 +0100456
danilchap56036ff2016-03-22 11:14:09 -0700457 return std::unique_ptr<rtcp::RtcpPacket>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000458}
459
danilchap56036ff2016-03-22 11:14:09 -0700460std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSDES(
Erik Språngf7c57762015-12-04 10:40:35 +0100461 const RtcpContext& ctx) {
Erik Språng0ea42d32015-06-25 14:46:16 +0200462 size_t length_cname = cname_.length();
henrikg91d6ede2015-09-17 00:24:34 -0700463 RTC_CHECK_LT(length_cname, static_cast<size_t>(RTCP_CNAME_SIZE));
niklase@google.com470e71d2011-07-07 08:21:25 +0000464
Erik Språngf7c57762015-12-04 10:40:35 +0100465 rtcp::Sdes* sdes = new rtcp::Sdes();
466 sdes->WithCName(ssrc_, cname_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200467
468 for (const auto it : csrc_cnames_)
Erik Språngf7c57762015-12-04 10:40:35 +0100469 sdes->WithCName(it.first, it.second);
Erik Språng0ea42d32015-06-25 14:46:16 +0200470
danilchap56036ff2016-03-22 11:14:09 -0700471 return std::unique_ptr<rtcp::RtcpPacket>(sdes);
niklase@google.com470e71d2011-07-07 08:21:25 +0000472}
473
danilchap56036ff2016-03-22 11:14:09 -0700474std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildRR(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100475 rtcp::ReceiverReport* report = new rtcp::ReceiverReport();
476 report->From(ssrc_);
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200477 for (auto it : report_blocks_)
Erik Språngf7c57762015-12-04 10:40:35 +0100478 report->WithReportBlock(it.second);
Erik Språng61be2a42015-04-27 13:32:52 +0200479
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200480 report_blocks_.clear();
danilchap56036ff2016-03-22 11:14:09 -0700481 return std::unique_ptr<rtcp::RtcpPacket>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000482}
483
danilchap56036ff2016-03-22 11:14:09 -0700484std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildPLI(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100485 rtcp::Pli* pli = new rtcp::Pli();
486 pli->From(ssrc_);
487 pli->To(remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200488
Erik Språng242e22b2015-05-11 10:17:43 +0200489 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
490 "RTCPSender::PLI");
491 ++packet_type_counter_.pli_packets;
492 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
493 ssrc_, packet_type_counter_.pli_packets);
494
danilchap56036ff2016-03-22 11:14:09 -0700495 return std::unique_ptr<rtcp::RtcpPacket>(pli);
Erik Språng61be2a42015-04-27 13:32:52 +0200496}
497
danilchap56036ff2016-03-22 11:14:09 -0700498std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildFIR(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100499 if (!ctx.repeat_)
sprang62dae192015-08-05 02:35:35 -0700500 ++sequence_number_fir_; // Do not increase if repetition.
niklase@google.com470e71d2011-07-07 08:21:25 +0000501
Erik Språngf7c57762015-12-04 10:40:35 +0100502 rtcp::Fir* fir = new rtcp::Fir();
503 fir->From(ssrc_);
Danil Chapovalov32e590e2016-01-22 11:04:56 +0100504 fir->WithRequestTo(remote_ssrc_, sequence_number_fir_);
Erik Språng242e22b2015-05-11 10:17:43 +0200505
506 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
507 "RTCPSender::FIR");
508 ++packet_type_counter_.fir_packets;
509 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
510 ssrc_, packet_type_counter_.fir_packets);
511
danilchap56036ff2016-03-22 11:14:09 -0700512 return std::unique_ptr<rtcp::RtcpPacket>(fir);
niklase@google.com470e71d2011-07-07 08:21:25 +0000513}
514
515/*
516 0 1 2 3
517 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
518 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
519 | First | Number | PictureID |
520 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
521*/
danilchap56036ff2016-03-22 11:14:09 -0700522std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSLI(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100523 rtcp::Sli* sli = new rtcp::Sli();
524 sli->From(ssrc_);
525 sli->To(remote_ssrc_);
sprang0365a272015-08-11 01:02:37 -0700526 // Crop picture id to 6 least significant bits.
Erik Språngf7c57762015-12-04 10:40:35 +0100527 sli->WithPictureId(ctx.picture_id_ & 0x3F);
sprang0365a272015-08-11 01:02:37 -0700528
danilchap56036ff2016-03-22 11:14:09 -0700529 return std::unique_ptr<rtcp::RtcpPacket>(sli);
niklase@google.com470e71d2011-07-07 08:21:25 +0000530}
531
532/*
533 0 1 2 3
534 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
535 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
536 | PB |0| Payload Type| Native RPSI bit string |
537 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
538 | defined per codec ... | Padding (0) |
539 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
540*/
541/*
542* Note: not generic made for VP8
543*/
danilchap56036ff2016-03-22 11:14:09 -0700544std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildRPSI(
Erik Språngf7c57762015-12-04 10:40:35 +0100545 const RtcpContext& ctx) {
546 if (ctx.feedback_state_.send_payload_type == 0xFF)
547 return nullptr;
Erik Språng242e22b2015-05-11 10:17:43 +0200548
Erik Språngf7c57762015-12-04 10:40:35 +0100549 rtcp::Rpsi* rpsi = new rtcp::Rpsi();
550 rpsi->From(ssrc_);
551 rpsi->To(remote_ssrc_);
552 rpsi->WithPayloadType(ctx.feedback_state_.send_payload_type);
553 rpsi->WithPictureId(ctx.picture_id_);
sprangcf7f54d2015-08-13 04:37:42 -0700554
danilchap56036ff2016-03-22 11:14:09 -0700555 return std::unique_ptr<rtcp::RtcpPacket>(rpsi);
niklase@google.com470e71d2011-07-07 08:21:25 +0000556}
557
danilchap56036ff2016-03-22 11:14:09 -0700558std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildREMB(
Erik Språngf7c57762015-12-04 10:40:35 +0100559 const RtcpContext& ctx) {
560 rtcp::Remb* remb = new rtcp::Remb();
561 remb->From(ssrc_);
sprangdd4edc52015-08-21 04:21:51 -0700562 for (uint32_t ssrc : remb_ssrcs_)
Erik Språngf7c57762015-12-04 10:40:35 +0100563 remb->AppliesTo(ssrc);
564 remb->WithBitrateBps(remb_bitrate_);
Erik Språng61be2a42015-04-27 13:32:52 +0200565
Erik Språng242e22b2015-05-11 10:17:43 +0200566 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
567 "RTCPSender::REMB");
568
danilchap56036ff2016-03-22 11:14:09 -0700569 return std::unique_ptr<rtcp::RtcpPacket>(remb);
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000570}
571
Erik Språng61be2a42015-04-27 13:32:52 +0200572void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
danilchap56036ff2016-03-22 11:14:09 -0700573 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200574 tmmbr_send_ = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000575}
576
danilchap56036ff2016-03-22 11:14:09 -0700577std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBR(
Erik Språngf7c57762015-12-04 10:40:35 +0100578 const RtcpContext& ctx) {
579 if (ctx.feedback_state_.module == nullptr)
580 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200581 // Before sending the TMMBR check the received TMMBN, only an owner is
582 // allowed to raise the bitrate:
583 // * If the sender is an owner of the TMMBN -> send TMMBR
584 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000585
Erik Språng61be2a42015-04-27 13:32:52 +0200586 // get current bounding set from RTCP receiver
587 bool tmmbrOwner = false;
588 // store in candidateSet, allocates one extra slot
Erik Språng242e22b2015-05-11 10:17:43 +0200589 TMMBRSet* candidateSet = tmmbr_help_.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000590
Erik Språng242e22b2015-05-11 10:17:43 +0200591 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
592 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
Erik Språng61be2a42015-04-27 13:32:52 +0200593 // since RTCPreceiver is not doing the reverse we should be fine
594 int32_t lengthOfBoundingSet =
danilchap6db6cdc2015-12-15 02:54:47 -0800595 ctx.feedback_state_.module->BoundingSet(&tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +0000596
Erik Språng61be2a42015-04-27 13:32:52 +0200597 if (lengthOfBoundingSet > 0) {
598 for (int32_t i = 0; i < lengthOfBoundingSet; i++) {
Erik Språng242e22b2015-05-11 10:17:43 +0200599 if (candidateSet->Tmmbr(i) == tmmbr_send_ &&
600 candidateSet->PacketOH(i) == packet_oh_send_) {
Erik Språngf7c57762015-12-04 10:40:35 +0100601 // Do not send the same tuple.
602 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200603 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000604 }
Erik Språng61be2a42015-04-27 13:32:52 +0200605 if (!tmmbrOwner) {
606 // use received bounding set as candidate set
607 // add current tuple
Erik Språng242e22b2015-05-11 10:17:43 +0200608 candidateSet->SetEntry(lengthOfBoundingSet, tmmbr_send_, packet_oh_send_,
609 ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200610 int numCandidates = lengthOfBoundingSet + 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000611
Erik Språng61be2a42015-04-27 13:32:52 +0200612 // find bounding set
Erik Språngf7c57762015-12-04 10:40:35 +0100613 TMMBRSet* boundingSet = nullptr;
Erik Språng242e22b2015-05-11 10:17:43 +0200614 int numBoundingSet = tmmbr_help_.FindTMMBRBoundingSet(boundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200615 if (numBoundingSet > 0 || numBoundingSet <= numCandidates)
Erik Språng242e22b2015-05-11 10:17:43 +0200616 tmmbrOwner = tmmbr_help_.IsOwner(ssrc_, numBoundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200617 if (!tmmbrOwner) {
Erik Språngf7c57762015-12-04 10:40:35 +0100618 // Did not enter bounding set, no meaning to send this request.
619 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200620 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000621 }
Erik Språng61be2a42015-04-27 13:32:52 +0200622 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000623
Erik Språngf7c57762015-12-04 10:40:35 +0100624 if (!tmmbr_send_)
625 return nullptr;
sprang81a3e602015-08-21 05:30:11 -0700626
Erik Språngf7c57762015-12-04 10:40:35 +0100627 rtcp::Tmmbr* tmmbr = new rtcp::Tmmbr();
628 tmmbr->From(ssrc_);
danilchapf174e3a2016-02-05 04:56:36 -0800629 rtcp::TmmbItem request;
630 request.set_ssrc(remote_ssrc_);
631 request.set_bitrate_bps(tmmbr_send_ * 1000);
632 request.set_packet_overhead(packet_oh_send_);
633 tmmbr->WithTmmbr(request);
Erik Språngf7c57762015-12-04 10:40:35 +0100634
danilchap56036ff2016-03-22 11:14:09 -0700635 return std::unique_ptr<rtcp::RtcpPacket>(tmmbr);
Erik Språng61be2a42015-04-27 13:32:52 +0200636}
637
danilchap56036ff2016-03-22 11:14:09 -0700638std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBN(
Erik Språngf7c57762015-12-04 10:40:35 +0100639 const RtcpContext& ctx) {
Erik Språng242e22b2015-05-11 10:17:43 +0200640 TMMBRSet* boundingSet = tmmbr_help_.BoundingSetToSend();
Erik Språngf7c57762015-12-04 10:40:35 +0100641 if (boundingSet == nullptr)
642 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200643
Erik Språngf7c57762015-12-04 10:40:35 +0100644 rtcp::Tmmbn* tmmbn = new rtcp::Tmmbn();
645 tmmbn->From(ssrc_);
sprangd83df502015-08-27 01:05:08 -0700646 for (uint32_t i = 0; i < boundingSet->lengthOfSet(); i++) {
647 if (boundingSet->Tmmbr(i) > 0) {
Erik Språngf7c57762015-12-04 10:40:35 +0100648 tmmbn->WithTmmbr(boundingSet->Ssrc(i), boundingSet->Tmmbr(i),
649 boundingSet->PacketOH(i));
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000650 }
Erik Språng61be2a42015-04-27 13:32:52 +0200651 }
sprangd83df502015-08-27 01:05:08 -0700652
danilchap56036ff2016-03-22 11:14:09 -0700653 return std::unique_ptr<rtcp::RtcpPacket>(tmmbn);
niklase@google.com470e71d2011-07-07 08:21:25 +0000654}
655
danilchap56036ff2016-03-22 11:14:09 -0700656std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildAPP(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100657 rtcp::App* app = new rtcp::App();
658 app->From(ssrc_);
659 app->WithSubType(app_sub_type_);
660 app->WithName(app_name_);
661 app->WithData(app_data_.get(), app_length_);
Erik Språng521875a2015-09-01 10:11:16 +0200662
danilchap56036ff2016-03-22 11:14:09 -0700663 return std::unique_ptr<rtcp::RtcpPacket>(app);
Erik Språng61be2a42015-04-27 13:32:52 +0200664}
665
danilchap56036ff2016-03-22 11:14:09 -0700666std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildNACK(
Erik Språngf7c57762015-12-04 10:40:35 +0100667 const RtcpContext& ctx) {
668 rtcp::Nack* nack = new rtcp::Nack();
669 nack->From(ssrc_);
670 nack->To(remote_ssrc_);
671 nack->WithList(ctx.nack_list_, ctx.nack_size_);
Erik Språng61be2a42015-04-27 13:32:52 +0200672
673 // Report stats.
674 NACKStringBuilder stringBuilder;
Erik Språngf7c57762015-12-04 10:40:35 +0100675 for (int idx = 0; idx < ctx.nack_size_; ++idx) {
676 stringBuilder.PushNACK(ctx.nack_list_[idx]);
677 nack_stats_.ReportRequest(ctx.nack_list_[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +0200678 }
Erik Språng61be2a42015-04-27 13:32:52 +0200679 packet_type_counter_.nack_requests = nack_stats_.requests();
680 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +0200681
682 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
683 "RTCPSender::NACK", "nacks",
684 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
685 ++packet_type_counter_.nack_packets;
686 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
687 ssrc_, packet_type_counter_.nack_packets);
688
danilchap56036ff2016-03-22 11:14:09 -0700689 return std::unique_ptr<rtcp::RtcpPacket>(nack);
Erik Språng61be2a42015-04-27 13:32:52 +0200690}
691
danilchap56036ff2016-03-22 11:14:09 -0700692std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildBYE(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100693 rtcp::Bye* bye = new rtcp::Bye();
694 bye->From(ssrc_);
sprangd8ee4f92015-08-24 03:25:19 -0700695 for (uint32_t csrc : csrcs_)
Erik Språngf7c57762015-12-04 10:40:35 +0100696 bye->WithCsrc(csrc);
sprangd8ee4f92015-08-24 03:25:19 -0700697
danilchap56036ff2016-03-22 11:14:09 -0700698 return std::unique_ptr<rtcp::RtcpPacket>(bye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000699}
700
danilchap56036ff2016-03-22 11:14:09 -0700701std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildReceiverReferenceTime(
Erik Språngf7c57762015-12-04 10:40:35 +0100702 const RtcpContext& ctx) {
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000703
Danil Chapovalov256e5b22016-01-15 14:16:24 +0100704 rtcp::ExtendedReports* xr = new rtcp::ExtendedReports();
Erik Språngf7c57762015-12-04 10:40:35 +0100705 xr->From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000706
Erik Språngca28fdc2015-08-31 14:00:50 +0200707 rtcp::Rrtr rrtr;
Danil Chapovalovfc47ed62015-12-07 14:46:35 +0100708 rrtr.WithNtp(NtpTime(ctx.ntp_sec_, ctx.ntp_frac_));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000709
danilchapde138822016-01-29 11:26:14 -0800710 xr->WithRrtr(rrtr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000711
Erik Språngca28fdc2015-08-31 14:00:50 +0200712 // TODO(sprang): Merge XR report sending to contain all of RRTR, DLRR, VOIP?
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000713
danilchap56036ff2016-03-22 11:14:09 -0700714 return std::unique_ptr<rtcp::RtcpPacket>(xr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000715}
716
danilchap56036ff2016-03-22 11:14:09 -0700717std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildDlrr(
Erik Språngf7c57762015-12-04 10:40:35 +0100718 const RtcpContext& ctx) {
Danil Chapovalov256e5b22016-01-15 14:16:24 +0100719 rtcp::ExtendedReports* xr = new rtcp::ExtendedReports();
Erik Språngf7c57762015-12-04 10:40:35 +0100720 xr->From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000721
Erik Språngca28fdc2015-08-31 14:00:50 +0200722 rtcp::Dlrr dlrr;
Erik Språngf7c57762015-12-04 10:40:35 +0100723 const RtcpReceiveTimeInfo& info = ctx.feedback_state_.last_xr_rr;
Erik Språngca28fdc2015-08-31 14:00:50 +0200724 dlrr.WithDlrrItem(info.sourceSSRC, info.lastRR, info.delaySinceLastRR);
725
danilchapde138822016-01-29 11:26:14 -0800726 xr->WithDlrr(dlrr);
Erik Språngca28fdc2015-08-31 14:00:50 +0200727
danilchap56036ff2016-03-22 11:14:09 -0700728 return std::unique_ptr<rtcp::RtcpPacket>(xr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000729}
730
Erik Språng242e22b2015-05-11 10:17:43 +0200731// TODO(sprang): Add a unit test for this, or remove if the code isn't used.
danilchap56036ff2016-03-22 11:14:09 -0700732std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildVoIPMetric(
Erik Språngf7c57762015-12-04 10:40:35 +0100733 const RtcpContext& context) {
Danil Chapovalov256e5b22016-01-15 14:16:24 +0100734 rtcp::ExtendedReports* xr = new rtcp::ExtendedReports();
Erik Språngf7c57762015-12-04 10:40:35 +0100735 xr->From(ssrc_);
Erik Språngca28fdc2015-08-31 14:00:50 +0200736
737 rtcp::VoipMetric voip;
738 voip.To(remote_ssrc_);
danilchap91941ae2015-12-15 07:06:36 -0800739 voip.WithVoipMetric(xr_voip_metric_);
Erik Språngca28fdc2015-08-31 14:00:50 +0200740
danilchapde138822016-01-29 11:26:14 -0800741 xr->WithVoipMetric(voip);
Erik Språngca28fdc2015-08-31 14:00:50 +0200742
danilchap56036ff2016-03-22 11:14:09 -0700743 return std::unique_ptr<rtcp::RtcpPacket>(xr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000744}
745
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000746int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200747 RTCPPacketType packetType,
748 int32_t nack_size,
749 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000750 bool repeat,
751 uint64_t pictureID) {
Erik Språng242e22b2015-05-11 10:17:43 +0200752 return SendCompoundRTCP(
753 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
754 nack_size, nack_list, repeat, pictureID);
755}
756
757int32_t RTCPSender::SendCompoundRTCP(
758 const FeedbackState& feedback_state,
Erik Språngf7c57762015-12-04 10:40:35 +0100759 const std::set<RTCPPacketType>& packet_types,
Erik Språng242e22b2015-05-11 10:17:43 +0200760 int32_t nack_size,
761 const uint16_t* nack_list,
762 bool repeat,
763 uint64_t pictureID) {
terelius429c3452016-01-21 05:42:04 -0800764 PacketContainer container(transport_, event_log_);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000765 {
danilchap56036ff2016-03-22 11:14:09 -0700766 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbosda903ea2015-10-02 02:36:56 -0700767 if (method_ == RtcpMode::kOff) {
Erik Språng61be2a42015-04-27 13:32:52 +0200768 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
769 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +0000770 }
Erik Språngf7c57762015-12-04 10:40:35 +0100771
772 // We need to send our NTP even if we haven't received any reports.
773 uint32_t ntp_sec;
774 uint32_t ntp_frac;
775 clock_->CurrentNtp(ntp_sec, ntp_frac);
776 RtcpContext context(feedback_state, nack_size, nack_list, repeat, pictureID,
danilchap56036ff2016-03-22 11:14:09 -0700777 ntp_sec, ntp_frac);
Erik Språngf7c57762015-12-04 10:40:35 +0100778
779 PrepareReport(packet_types, feedback_state);
780
danilchap56036ff2016-03-22 11:14:09 -0700781 std::unique_ptr<rtcp::RtcpPacket> packet_bye;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800782
Erik Språngf7c57762015-12-04 10:40:35 +0100783 auto it = report_flags_.begin();
784 while (it != report_flags_.end()) {
785 auto builder_it = builders_.find(it->type);
786 RTC_DCHECK(builder_it != builders_.end());
787 if (it->is_volatile) {
788 report_flags_.erase(it++);
789 } else {
790 ++it;
791 }
792
793 BuilderFunc func = builder_it->second;
danilchap56036ff2016-03-22 11:14:09 -0700794 std::unique_ptr<rtcp::RtcpPacket> packet = (this->*func)(context);
Erik Språngf7c57762015-12-04 10:40:35 +0100795 if (packet.get() == nullptr)
796 return -1;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800797 // If there is a BYE, don't append now - save it and append it
798 // at the end later.
799 if (builder_it->first == kRtcpBye) {
800 packet_bye = std::move(packet);
801 } else {
802 container.Append(packet.release());
803 }
804 }
805
806 // Append the BYE now at the end
807 if (packet_bye) {
808 container.Append(packet_bye.release());
Erik Språngf7c57762015-12-04 10:40:35 +0100809 }
810
811 if (packet_type_counter_observer_ != nullptr) {
812 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
813 remote_ssrc_, packet_type_counter_);
814 }
815
816 RTC_DCHECK(AllVolatileFlagsConsumed());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000817 }
Erik Språng61be2a42015-04-27 13:32:52 +0200818
danilchap41befce2016-03-30 11:11:51 -0700819 size_t bytes_sent = container.SendPackets(max_payload_length_);
Erik Språngf7c57762015-12-04 10:40:35 +0100820 return bytes_sent == 0 ? -1 : 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000821}
822
Erik Språngf7c57762015-12-04 10:40:35 +0100823void RTCPSender::PrepareReport(const std::set<RTCPPacketType>& packetTypes,
824 const FeedbackState& feedback_state) {
Erik Språng242e22b2015-05-11 10:17:43 +0200825 // Add all flags as volatile. Non volatile entries will not be overwritten
826 // and all new volatile flags added will be consumed by the end of this call.
827 SetFlags(packetTypes, true);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000828
Erik Språng61be2a42015-04-27 13:32:52 +0200829 if (packet_type_counter_.first_packet_time_ms == -1)
Erik Språng242e22b2015-05-11 10:17:43 +0200830 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språng61be2a42015-04-27 13:32:52 +0200831
Erik Språng242e22b2015-05-11 10:17:43 +0200832 bool generate_report;
833 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
834 // Report type already explicitly set, don't automatically populate.
835 generate_report = true;
henrikg91d6ede2015-09-17 00:24:34 -0700836 RTC_DCHECK(ConsumeFlag(kRtcpReport) == false);
Erik Språng242e22b2015-05-11 10:17:43 +0200837 } else {
838 generate_report =
pbosda903ea2015-10-02 02:36:56 -0700839 (ConsumeFlag(kRtcpReport) && method_ == RtcpMode::kReducedSize) ||
840 method_ == RtcpMode::kCompound;
Erik Språng242e22b2015-05-11 10:17:43 +0200841 if (generate_report)
842 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000843 }
844
Erik Språng0ea42d32015-06-25 14:46:16 +0200845 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
Erik Språng242e22b2015-05-11 10:17:43 +0200846 SetFlag(kRtcpSdes, true);
847
Erik Språng242e22b2015-05-11 10:17:43 +0200848 if (generate_report) {
849 if (!sending_ && xr_send_receiver_reference_time_enabled_)
850 SetFlag(kRtcpXrReceiverReferenceTime, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200851 if (feedback_state.has_last_xr_rr)
Erik Språng242e22b2015-05-11 10:17:43 +0200852 SetFlag(kRtcpXrDlrrReportBlock, true);
853
854 // generate next time to send an RTCP report
danilchap47a740b2015-12-15 00:30:07 -0800855 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000856
danilchap47a740b2015-12-15 00:30:07 -0800857 if (!audio_) {
Erik Språng242e22b2015-05-11 10:17:43 +0200858 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200859 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
860 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
861 if (send_bitrate_kbit != 0)
862 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000863 }
Erik Språng61be2a42015-04-27 13:32:52 +0200864 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
865 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
Erik Språng61be2a42015-04-27 13:32:52 +0200866 }
danilchap47a740b2015-12-15 00:30:07 -0800867 // The interval between RTCP packets is varied randomly over the
868 // range [1/2,3/2] times the calculated interval.
869 uint32_t timeToNext =
870 random_.Rand(minIntervalMs * 1 / 2, minIntervalMs * 3 / 2);
Erik Språng242e22b2015-05-11 10:17:43 +0200871 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000872
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000873 StatisticianMap statisticians =
874 receive_statistics_->GetActiveStatisticians();
danilchapa72e7342015-12-22 08:07:45 -0800875 RTC_DCHECK(report_blocks_.empty());
876 for (auto& it : statisticians) {
877 AddReportBlock(feedback_state, it.first, it.second);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000878 }
879 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000880}
881
danilchapa72e7342015-12-22 08:07:45 -0800882bool RTCPSender::AddReportBlock(const FeedbackState& feedback_state,
883 uint32_t ssrc,
884 StreamStatistician* statistician) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000885 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000886 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000887 if (!statistician->GetStatistics(&stats, true))
888 return false;
danilchapa72e7342015-12-22 08:07:45 -0800889
890 if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) {
891 LOG(LS_WARNING) << "Too many report blocks.";
892 return false;
893 }
894 RTC_DCHECK(report_blocks_.find(ssrc) == report_blocks_.end());
895 rtcp::ReportBlock* block = &report_blocks_[ssrc];
896 block->To(ssrc);
897 block->WithFractionLost(stats.fraction_lost);
898 if (!block->WithCumulativeLost(stats.cumulative_lost)) {
899 report_blocks_.erase(ssrc);
900 LOG(LS_WARNING) << "Cumulative lost is oversized.";
901 return false;
902 }
903 block->WithExtHighestSeqNum(stats.extended_max_sequence_number);
904 block->WithJitter(stats.jitter);
905 block->WithLastSr(feedback_state.remote_sr);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000906
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200907 // TODO(sprang): Do we really need separate time stamps for each report?
908 // Get our NTP as late as possible to avoid a race.
909 uint32_t ntp_secs;
910 uint32_t ntp_frac;
911 clock_->CurrentNtp(ntp_secs, ntp_frac);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000912
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200913 // Delay since last received report.
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000914 if ((feedback_state.last_rr_ntp_secs != 0) ||
915 (feedback_state.last_rr_ntp_frac != 0)) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200916 // Get the 16 lowest bits of seconds and the 16 highest bits of fractions.
917 uint32_t now = ntp_secs & 0x0000FFFF;
Erik Språng61be2a42015-04-27 13:32:52 +0200918 now <<= 16;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200919 now += (ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000920
Erik Språng61be2a42015-04-27 13:32:52 +0200921 uint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
922 receiveTime <<= 16;
923 receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000924
danilchapa72e7342015-12-22 08:07:45 -0800925 block->WithDelayLastSr(now - receiveTime);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000926 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000927 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000928}
929
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000930void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
danilchap56036ff2016-03-22 11:14:09 -0700931 RTC_DCHECK_LE(csrcs.size(), static_cast<size_t>(kRtpCsrcSize));
932 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000933 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +0000934}
935
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000936int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
937 uint32_t name,
938 const uint8_t* data,
939 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +0200940 if (length % 4 != 0) {
941 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
942 return -1;
943 }
danilchap56036ff2016-03-22 11:14:09 -0700944 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000945
Erik Språng242e22b2015-05-11 10:17:43 +0200946 SetFlag(kRtcpApp, true);
947 app_sub_type_ = subType;
948 app_name_ = name;
949 app_data_.reset(new uint8_t[length]);
950 app_length_ = length;
951 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +0200952 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000953}
954
Erik Språng61be2a42015-04-27 13:32:52 +0200955int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
danilchap56036ff2016-03-22 11:14:09 -0700956 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200957 memcpy(&xr_voip_metric_, VoIPMetric, sizeof(RTCPVoIPMetric));
niklase@google.com470e71d2011-07-07 08:21:25 +0000958
Erik Språng242e22b2015-05-11 10:17:43 +0200959 SetFlag(kRtcpXrVoipMetric, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200960 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000961}
962
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000963void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700964 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200965 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000966}
967
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000968bool RTCPSender::RtcpXrReceiverReferenceTime() const {
danilchap56036ff2016-03-22 11:14:09 -0700969 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200970 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000971}
972
niklase@google.com470e71d2011-07-07 08:21:25 +0000973// no callbacks allowed inside this function
Peter Boström9d0c4322016-02-16 17:59:27 +0100974int32_t RTCPSender::SetTMMBN(const TMMBRSet* boundingSet) {
danilchap56036ff2016-03-22 11:14:09 -0700975 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000976
Peter Boström9d0c4322016-02-16 17:59:27 +0100977 if (0 == tmmbr_help_.SetTMMBRBoundingSetToSend(boundingSet)) {
Erik Språng242e22b2015-05-11 10:17:43 +0200978 SetFlag(kRtcpTmmbn, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200979 return 0;
980 }
981 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000982}
Erik Språng61be2a42015-04-27 13:32:52 +0200983
Erik Språng242e22b2015-05-11 10:17:43 +0200984void RTCPSender::SetFlag(RTCPPacketType type, bool is_volatile) {
985 report_flags_.insert(ReportFlag(type, is_volatile));
986}
987
988void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
989 bool is_volatile) {
990 for (RTCPPacketType type : types)
991 SetFlag(type, is_volatile);
992}
993
994bool RTCPSender::IsFlagPresent(RTCPPacketType type) const {
995 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
996}
997
998bool RTCPSender::ConsumeFlag(RTCPPacketType type, bool forced) {
999 auto it = report_flags_.find(ReportFlag(type, false));
1000 if (it == report_flags_.end())
1001 return false;
1002 if (it->is_volatile || forced)
1003 report_flags_.erase((it));
1004 return true;
1005}
1006
1007bool RTCPSender::AllVolatileFlagsConsumed() const {
1008 for (const ReportFlag& flag : report_flags_) {
1009 if (flag.is_volatile)
1010 return false;
1011 }
1012 return true;
1013}
1014
sprang233bd872015-09-08 13:25:16 -07001015bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
sprang233bd872015-09-08 13:25:16 -07001016 class Sender : public rtcp::RtcpPacket::PacketReadyCallback {
1017 public:
terelius429c3452016-01-21 05:42:04 -08001018 Sender(Transport* transport, RtcEventLog* event_log)
1019 : transport_(transport), event_log_(event_log), send_failure_(false) {}
sprang233bd872015-09-08 13:25:16 -07001020
1021 void OnPacketReady(uint8_t* data, size_t length) override {
terelius429c3452016-01-21 05:42:04 -08001022 if (transport_->SendRtcp(data, length)) {
1023 if (event_log_) {
1024 event_log_->LogRtcpPacket(kOutgoingPacket, MediaType::ANY, data,
1025 length);
1026 }
1027 } else {
sprang233bd872015-09-08 13:25:16 -07001028 send_failure_ = true;
terelius429c3452016-01-21 05:42:04 -08001029 }
sprang233bd872015-09-08 13:25:16 -07001030 }
1031
1032 Transport* const transport_;
terelius429c3452016-01-21 05:42:04 -08001033 RtcEventLog* const event_log_;
sprang233bd872015-09-08 13:25:16 -07001034 bool send_failure_;
terelius429c3452016-01-21 05:42:04 -08001035 // TODO(terelius): We would like to
1036 // RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(Sender);
1037 // but we can't because of an incorrect warning (C4822) in MVS 2013.
1038 } sender(transport_, event_log_);
sprang233bd872015-09-08 13:25:16 -07001039
danilchap41befce2016-03-30 11:11:51 -07001040 RTC_DCHECK_LE(max_payload_length_, static_cast<size_t>(IP_PACKET_SIZE));
sprang233bd872015-09-08 13:25:16 -07001041 uint8_t buffer[IP_PACKET_SIZE];
danilchap41befce2016-03-30 11:11:51 -07001042 return packet.BuildExternalBuffer(buffer, max_payload_length_, &sender) &&
sprang233bd872015-09-08 13:25:16 -07001043 !sender.send_failure_;
1044}
1045
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001046} // namespace webrtc