blob: d4c1cd1e1fd7ccfeeadbb611c82b7f16eb51fcd9 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000011#include "webrtc/modules/rtp_rtcp/source/rtcp_sender.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
stefan@webrtc.org9354cc92012-06-07 08:10:14 +000013#include <string.h> // memcpy
niklase@google.com470e71d2011-07-07 08:21:25 +000014
Danil Chapovalov70ffead2016-07-20 15:26:59 +020015#include <utility>
16
Erik Språng61be2a42015-04-27 13:32:52 +020017#include "webrtc/base/checks.h"
kwiberg4485ffb2016-04-26 08:14:39 -070018#include "webrtc/base/constructormagic.h"
Peter Boströmebc0b4e2015-10-28 16:39:33 +010019#include "webrtc/base/logging.h"
tommie4f96502015-10-20 23:00:48 -070020#include "webrtc/base/trace_event.h"
terelius429c3452016-01-21 05:42:04 -080021#include "webrtc/call.h"
22#include "webrtc/call/rtc_event_log.h"
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000023#include "webrtc/common_types.h"
danilchap0219c9b2015-11-18 05:56:53 -080024#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/app.h"
danilchap50c51362015-11-22 09:03:11 -080025#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/bye.h"
danilchap2f7dea12016-01-13 02:03:04 -080026#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/compound_packet.h"
Danil Chapovalov256e5b22016-01-15 14:16:24 +010027#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_reports.h"
Danil Chapovalov5679da12016-01-15 13:19:53 +010028#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/fir.h"
danilchapa8890a52015-12-22 03:43:04 -080029#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/nack.h"
danilchapf8385ad2015-11-27 05:36:09 -080030#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/pli.h"
Danil Chapovalov97f7e132015-12-04 16:13:30 +010031#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
Danil Chapovalova5eba6c2016-01-15 12:40:15 +010032#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/remb.h"
Danil Chapovalov2c132972016-01-15 15:21:21 +010033#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rpsi.h"
Danil Chapovalov1567d0b2016-01-15 17:34:27 +010034#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sdes.h"
danilchap34ed2b92016-01-18 02:43:32 -080035#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sender_report.h"
danilchap92e677a2016-01-12 10:04:52 -080036#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sli.h"
danilchapef3d8052016-01-11 03:31:08 -080037#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbn.h"
danilchap7e8145f2016-01-11 11:49:19 -080038#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbr.h"
sprang233bd872015-09-08 13:25:16 -070039#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
tommie4f96502015-10-20 23:00:48 -070040#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
danilchap13deaad2016-05-24 13:25:27 -070041#include "webrtc/modules/rtp_rtcp/source/tmmbr_help.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000042
niklase@google.com470e71d2011-07-07 08:21:25 +000043namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000044
Erik Språng61be2a42015-04-27 13:32:52 +020045NACKStringBuilder::NACKStringBuilder()
danilchap162abd32015-12-10 02:39:40 -080046 : stream_(""), count_(0), prevNack_(0), consecutive_(false) {}
edjee@google.com79b02892013-04-04 19:43:34 +000047
pbos@webrtc.orgf3e4cee2013-07-31 15:17:19 +000048NACKStringBuilder::~NACKStringBuilder() {}
49
danilchap162abd32015-12-10 02:39:40 -080050void NACKStringBuilder::PushNACK(uint16_t nack) {
Erik Språng242e22b2015-05-11 10:17:43 +020051 if (count_ == 0) {
52 stream_ << nack;
53 } else if (nack == prevNack_ + 1) {
54 consecutive_ = true;
Erik Språng61be2a42015-04-27 13:32:52 +020055 } else {
Erik Språng242e22b2015-05-11 10:17:43 +020056 if (consecutive_) {
57 stream_ << "-" << prevNack_;
58 consecutive_ = false;
edjee@google.com79b02892013-04-04 19:43:34 +000059 }
Erik Språng242e22b2015-05-11 10:17:43 +020060 stream_ << "," << nack;
Erik Språng61be2a42015-04-27 13:32:52 +020061 }
Erik Språng242e22b2015-05-11 10:17:43 +020062 count_++;
63 prevNack_ = nack;
edjee@google.com79b02892013-04-04 19:43:34 +000064}
65
Erik Språng61be2a42015-04-27 13:32:52 +020066std::string NACKStringBuilder::GetResult() {
Erik Språng242e22b2015-05-11 10:17:43 +020067 if (consecutive_) {
68 stream_ << "-" << prevNack_;
69 consecutive_ = false;
Erik Språng61be2a42015-04-27 13:32:52 +020070 }
Erik Språng242e22b2015-05-11 10:17:43 +020071 return stream_.str();
edjee@google.com79b02892013-04-04 19:43:34 +000072}
73
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000074RTCPSender::FeedbackState::FeedbackState()
75 : send_payload_type(0),
76 frequency_hz(0),
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +000077 packets_sent(0),
78 media_bytes_sent(0),
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000079 send_bitrate(0),
80 last_rr_ntp_secs(0),
81 last_rr_ntp_frac(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000082 remote_sr(0),
Erik Språng61be2a42015-04-27 13:32:52 +020083 has_last_xr_rr(false),
danilchap162abd32015-12-10 02:39:40 -080084 module(nullptr) {}
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000085
danilchap2f7dea12016-01-13 02:03:04 -080086class PacketContainer : public rtcp::CompoundPacket,
Erik Språngf7c57762015-12-04 10:40:35 +010087 public rtcp::RtcpPacket::PacketReadyCallback {
88 public:
terelius429c3452016-01-21 05:42:04 -080089 PacketContainer(Transport* transport, RtcEventLog* event_log)
90 : transport_(transport), event_log_(event_log), bytes_sent_(0) {}
Erik Språngf7c57762015-12-04 10:40:35 +010091 virtual ~PacketContainer() {
92 for (RtcpPacket* packet : appended_packets_)
93 delete packet;
94 }
95
96 void OnPacketReady(uint8_t* data, size_t length) override {
terelius429c3452016-01-21 05:42:04 -080097 if (transport_->SendRtcp(data, length)) {
Erik Språngf7c57762015-12-04 10:40:35 +010098 bytes_sent_ += length;
terelius429c3452016-01-21 05:42:04 -080099 if (event_log_) {
100 event_log_->LogRtcpPacket(kOutgoingPacket, MediaType::ANY, data,
101 length);
102 }
103 }
Erik Språngf7c57762015-12-04 10:40:35 +0100104 }
105
danilchap41befce2016-03-30 11:11:51 -0700106 size_t SendPackets(size_t max_payload_length) {
107 RTC_DCHECK_LE(max_payload_length, static_cast<size_t>(IP_PACKET_SIZE));
108 uint8_t buffer[IP_PACKET_SIZE];
109 BuildExternalBuffer(buffer, max_payload_length, this);
Erik Språngf7c57762015-12-04 10:40:35 +0100110 return bytes_sent_;
111 }
112
113 private:
114 Transport* transport_;
terelius429c3452016-01-21 05:42:04 -0800115 RtcEventLog* const event_log_;
Erik Språngf7c57762015-12-04 10:40:35 +0100116 size_t bytes_sent_;
terelius429c3452016-01-21 05:42:04 -0800117
118 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(PacketContainer);
Erik Språngf7c57762015-12-04 10:40:35 +0100119};
120
121class RTCPSender::RtcpContext {
122 public:
Erik Språng242e22b2015-05-11 10:17:43 +0200123 RtcpContext(const FeedbackState& feedback_state,
124 int32_t nack_size,
125 const uint16_t* nack_list,
126 bool repeat,
127 uint64_t picture_id,
Erik Språngf7c57762015-12-04 10:40:35 +0100128 uint32_t ntp_sec,
danilchap56036ff2016-03-22 11:14:09 -0700129 uint32_t ntp_frac)
Erik Språngf7c57762015-12-04 10:40:35 +0100130 : feedback_state_(feedback_state),
131 nack_size_(nack_size),
132 nack_list_(nack_list),
133 repeat_(repeat),
134 picture_id_(picture_id),
135 ntp_sec_(ntp_sec),
danilchap56036ff2016-03-22 11:14:09 -0700136 ntp_frac_(ntp_frac) {}
Erik Språng242e22b2015-05-11 10:17:43 +0200137
Erik Språngf7c57762015-12-04 10:40:35 +0100138 const FeedbackState& feedback_state_;
139 const int32_t nack_size_;
140 const uint16_t* nack_list_;
141 const bool repeat_;
142 const uint64_t picture_id_;
143 const uint32_t ntp_sec_;
144 const uint32_t ntp_frac_;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200145};
146
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000147RTCPSender::RTCPSender(
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000148 bool audio,
149 Clock* clock,
150 ReceiveStatistics* receive_statistics,
sprang86fd9ed2015-09-29 04:45:43 -0700151 RtcpPacketTypeCounterObserver* packet_type_counter_observer,
terelius429c3452016-01-21 05:42:04 -0800152 RtcEventLog* event_log,
sprang86fd9ed2015-09-29 04:45:43 -0700153 Transport* outgoing_transport)
Peter Boströmac547a62015-09-17 23:03:57 +0200154 : audio_(audio),
Erik Språng242e22b2015-05-11 10:17:43 +0200155 clock_(clock),
danilchap47a740b2015-12-15 00:30:07 -0800156 random_(clock_->TimeInMicroseconds()),
pbosda903ea2015-10-02 02:36:56 -0700157 method_(RtcpMode::kOff),
terelius429c3452016-01-21 05:42:04 -0800158 event_log_(event_log),
sprang86fd9ed2015-09-29 04:45:43 -0700159 transport_(outgoing_transport),
Erik Språng242e22b2015-05-11 10:17:43 +0200160 using_nack_(false),
161 sending_(false),
162 remb_enabled_(false),
Erik Språng242e22b2015-05-11 10:17:43 +0200163 next_time_to_send_rtcp_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000164 start_timestamp_(0),
165 last_rtp_timestamp_(0),
166 last_frame_capture_time_ms_(-1),
Erik Språng242e22b2015-05-11 10:17:43 +0200167 ssrc_(0),
168 remote_ssrc_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000169 receive_statistics_(receive_statistics),
niklase@google.com470e71d2011-07-07 08:21:25 +0000170
Erik Språng242e22b2015-05-11 10:17:43 +0200171 sequence_number_fir_(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000172
Erik Språng242e22b2015-05-11 10:17:43 +0200173 remb_bitrate_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000174
Erik Språng242e22b2015-05-11 10:17:43 +0200175 tmmbr_send_(0),
176 packet_oh_send_(0),
danilchap41befce2016-03-30 11:11:51 -0700177 max_payload_length_(IP_PACKET_SIZE - 28), // IPv4 + UDP by default.
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000178
Erik Språng242e22b2015-05-11 10:17:43 +0200179 app_sub_type_(0),
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200180 app_name_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200181 app_data_(nullptr),
182 app_length_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000183
Erik Språng242e22b2015-05-11 10:17:43 +0200184 xr_send_receiver_reference_time_enabled_(false),
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000185 packet_type_counter_observer_(packet_type_counter_observer) {
sprang86fd9ed2015-09-29 04:45:43 -0700186 RTC_DCHECK(transport_ != nullptr);
Erik Språng242e22b2015-05-11 10:17:43 +0200187
188 builders_[kRtcpSr] = &RTCPSender::BuildSR;
189 builders_[kRtcpRr] = &RTCPSender::BuildRR;
Erik Språng0ea42d32015-06-25 14:46:16 +0200190 builders_[kRtcpSdes] = &RTCPSender::BuildSDES;
Erik Språng242e22b2015-05-11 10:17:43 +0200191 builders_[kRtcpPli] = &RTCPSender::BuildPLI;
192 builders_[kRtcpFir] = &RTCPSender::BuildFIR;
193 builders_[kRtcpSli] = &RTCPSender::BuildSLI;
194 builders_[kRtcpRpsi] = &RTCPSender::BuildRPSI;
195 builders_[kRtcpRemb] = &RTCPSender::BuildREMB;
196 builders_[kRtcpBye] = &RTCPSender::BuildBYE;
197 builders_[kRtcpApp] = &RTCPSender::BuildAPP;
198 builders_[kRtcpTmmbr] = &RTCPSender::BuildTMMBR;
199 builders_[kRtcpTmmbn] = &RTCPSender::BuildTMMBN;
200 builders_[kRtcpNack] = &RTCPSender::BuildNACK;
201 builders_[kRtcpXrVoipMetric] = &RTCPSender::BuildVoIPMetric;
202 builders_[kRtcpXrReceiverReferenceTime] =
203 &RTCPSender::BuildReceiverReferenceTime;
204 builders_[kRtcpXrDlrrReportBlock] = &RTCPSender::BuildDlrr;
niklase@google.com470e71d2011-07-07 08:21:25 +0000205}
206
danilchap162abd32015-12-10 02:39:40 -0800207RTCPSender::~RTCPSender() {}
niklase@google.com470e71d2011-07-07 08:21:25 +0000208
pbosda903ea2015-10-02 02:36:56 -0700209RtcpMode RTCPSender::Status() const {
danilchap56036ff2016-03-22 11:14:09 -0700210 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200211 return method_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000212}
213
skvlad1c392cc2016-04-01 14:46:44 -0700214void RTCPSender::SetRTCPStatus(RtcpMode new_method) {
danilchap56036ff2016-03-22 11:14:09 -0700215 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000216
skvlad1c392cc2016-04-01 14:46:44 -0700217 if (method_ == RtcpMode::kOff && new_method != RtcpMode::kOff) {
218 // When switching on, reschedule the next packet
219 next_time_to_send_rtcp_ =
Erik Språng242e22b2015-05-11 10:17:43 +0200220 clock_->TimeInMilliseconds() +
221 (audio_ ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
skvlad1c392cc2016-04-01 14:46:44 -0700222 }
223 method_ = new_method;
niklase@google.com470e71d2011-07-07 08:21:25 +0000224}
225
Erik Språng61be2a42015-04-27 13:32:52 +0200226bool RTCPSender::Sending() const {
danilchap56036ff2016-03-22 11:14:09 -0700227 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200228 return sending_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000229}
230
Erik Språng61be2a42015-04-27 13:32:52 +0200231int32_t RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
232 bool sending) {
233 bool sendRTCPBye = false;
234 {
danilchap56036ff2016-03-22 11:14:09 -0700235 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000236
pbosda903ea2015-10-02 02:36:56 -0700237 if (method_ != RtcpMode::kOff) {
Erik Språng242e22b2015-05-11 10:17:43 +0200238 if (sending == false && sending_ == true) {
Erik Språng61be2a42015-04-27 13:32:52 +0200239 // Trigger RTCP bye
240 sendRTCPBye = true;
241 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000242 }
Erik Språng242e22b2015-05-11 10:17:43 +0200243 sending_ = sending;
Erik Språng61be2a42015-04-27 13:32:52 +0200244 }
245 if (sendRTCPBye)
246 return SendRTCP(feedback_state, kRtcpBye);
247 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000248}
249
Erik Språng61be2a42015-04-27 13:32:52 +0200250bool RTCPSender::REMB() const {
danilchap56036ff2016-03-22 11:14:09 -0700251 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200252 return remb_enabled_;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000253}
254
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000255void RTCPSender::SetREMBStatus(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700256 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200257 remb_enabled_ = enable;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000258}
259
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000260void RTCPSender::SetREMBData(uint32_t bitrate,
261 const std::vector<uint32_t>& ssrcs) {
danilchap56036ff2016-03-22 11:14:09 -0700262 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200263 remb_bitrate_ = bitrate;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000264 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000265
Erik Språng242e22b2015-05-11 10:17:43 +0200266 if (remb_enabled_)
267 SetFlag(kRtcpRemb, false);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000268 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
269 // throttled by the caller.
Erik Språng242e22b2015-05-11 10:17:43 +0200270 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000271}
272
Erik Språng61be2a42015-04-27 13:32:52 +0200273bool RTCPSender::TMMBR() const {
danilchap56036ff2016-03-22 11:14:09 -0700274 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200275 return IsFlagPresent(RTCPPacketType::kRtcpTmmbr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000276}
277
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000278void RTCPSender::SetTMMBRStatus(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700279 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200280 if (enable) {
281 SetFlag(RTCPPacketType::kRtcpTmmbr, false);
282 } else {
283 ConsumeFlag(RTCPPacketType::kRtcpTmmbr, true);
284 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000285}
286
danilchap41befce2016-03-30 11:11:51 -0700287void RTCPSender::SetMaxPayloadLength(size_t max_payload_length) {
288 max_payload_length_ = max_payload_length;
289}
290
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000291void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
danilchap56036ff2016-03-22 11:14:09 -0700292 rtc::CritScope lock(&critical_section_rtcp_sender_);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000293 start_timestamp_ = start_timestamp;
294}
295
296void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
297 int64_t capture_time_ms) {
danilchap56036ff2016-03-22 11:14:09 -0700298 rtc::CritScope lock(&critical_section_rtcp_sender_);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000299 last_rtp_timestamp_ = rtp_timestamp;
300 if (capture_time_ms < 0) {
301 // We don't currently get a capture time from VoiceEngine.
Erik Språng242e22b2015-05-11 10:17:43 +0200302 last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000303 } else {
304 last_frame_capture_time_ms_ = capture_time_ms;
305 }
306}
307
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000308void RTCPSender::SetSSRC(uint32_t ssrc) {
danilchap56036ff2016-03-22 11:14:09 -0700309 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000310
Erik Språng242e22b2015-05-11 10:17:43 +0200311 if (ssrc_ != 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200312 // not first SetSSRC, probably due to a collision
313 // schedule a new RTCP report
314 // make sure that we send a RTP packet
Erik Språng242e22b2015-05-11 10:17:43 +0200315 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
Erik Språng61be2a42015-04-27 13:32:52 +0200316 }
Erik Språng242e22b2015-05-11 10:17:43 +0200317 ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000318}
319
Erik Språng61be2a42015-04-27 13:32:52 +0200320void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
danilchap56036ff2016-03-22 11:14:09 -0700321 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200322 remote_ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000323}
324
Peter Boström9ba52f82015-06-01 14:12:28 +0200325int32_t RTCPSender::SetCNAME(const char* c_name) {
326 if (!c_name)
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000327 return -1;
328
henrikg91d6ede2015-09-17 00:24:34 -0700329 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
danilchap56036ff2016-03-22 11:14:09 -0700330 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200331 cname_ = c_name;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000332 return 0;
333}
334
Erik Språng0ea42d32015-06-25 14:46:16 +0200335int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC, const char* c_name) {
danilchap56036ff2016-03-22 11:14:09 -0700336 RTC_DCHECK(c_name);
henrikg91d6ede2015-09-17 00:24:34 -0700337 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
danilchap56036ff2016-03-22 11:14:09 -0700338 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200339 if (csrc_cnames_.size() >= kRtpCsrcSize)
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000340 return -1;
Erik Språng0ea42d32015-06-25 14:46:16 +0200341
342 csrc_cnames_[SSRC] = c_name;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000343 return 0;
344}
345
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000346int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
danilchap56036ff2016-03-22 11:14:09 -0700347 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200348 auto it = csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000349
Erik Språng242e22b2015-05-11 10:17:43 +0200350 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000351 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200352
Erik Språng242e22b2015-05-11 10:17:43 +0200353 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000354 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000355}
356
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000357bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
danilchap162abd32015-12-10 02:39:40 -0800358 /*
359 For audio we use a fix 5 sec interval
niklase@google.com470e71d2011-07-07 08:21:25 +0000360
danilchap162abd32015-12-10 02:39:40 -0800361 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
362 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
363 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000364
365
danilchap162abd32015-12-10 02:39:40 -0800366 From RFC 3550
niklase@google.com470e71d2011-07-07 08:21:25 +0000367
danilchap162abd32015-12-10 02:39:40 -0800368 MAX RTCP BW is 5% if the session BW
369 A send report is approximately 65 bytes inc CNAME
370 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000371
danilchap162abd32015-12-10 02:39:40 -0800372 The RECOMMENDED value for the reduced minimum in seconds is 360
373 divided by the session bandwidth in kilobits/second. This minimum
374 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
niklase@google.com470e71d2011-07-07 08:21:25 +0000375
danilchap162abd32015-12-10 02:39:40 -0800376 If the participant has not yet sent an RTCP packet (the variable
377 initial is true), the constant Tmin is set to 2.5 seconds, else it
378 is set to 5 seconds.
niklase@google.com470e71d2011-07-07 08:21:25 +0000379
danilchap162abd32015-12-10 02:39:40 -0800380 The interval between RTCP packets is varied randomly over the
381 range [0.5,1.5] times the calculated interval to avoid unintended
382 synchronization of all participants
niklase@google.com470e71d2011-07-07 08:21:25 +0000383
danilchap162abd32015-12-10 02:39:40 -0800384 if we send
385 If the participant is a sender (we_sent true), the constant C is
386 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
387 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
388 number of senders.
niklase@google.com470e71d2011-07-07 08:21:25 +0000389
danilchap162abd32015-12-10 02:39:40 -0800390 if we receive only
391 If we_sent is not true, the constant C is set
392 to the average RTCP packet size divided by 75% of the RTCP
393 bandwidth. The constant n is set to the number of receivers
394 (members - senders). If the number of senders is greater than
395 25%, senders and receivers are treated together.
niklase@google.com470e71d2011-07-07 08:21:25 +0000396
danilchap162abd32015-12-10 02:39:40 -0800397 reconsideration NOT required for peer-to-peer
398 "timer reconsideration" is
399 employed. This algorithm implements a simple back-off mechanism
400 which causes users to hold back RTCP packet transmission if the
401 group sizes are increasing.
niklase@google.com470e71d2011-07-07 08:21:25 +0000402
danilchap162abd32015-12-10 02:39:40 -0800403 n = number of members
404 C = avg_size/(rtcpBW/4)
niklase@google.com470e71d2011-07-07 08:21:25 +0000405
danilchap162abd32015-12-10 02:39:40 -0800406 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
niklase@google.com470e71d2011-07-07 08:21:25 +0000407
danilchap162abd32015-12-10 02:39:40 -0800408 4. The calculated interval T is set to a number uniformly distributed
409 between 0.5 and 1.5 times the deterministic calculated interval.
niklase@google.com470e71d2011-07-07 08:21:25 +0000410
danilchap162abd32015-12-10 02:39:40 -0800411 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
412 for the fact that the timer reconsideration algorithm converges to
413 a value of the RTCP bandwidth below the intended average
414 */
niklase@google.com470e71d2011-07-07 08:21:25 +0000415
Erik Språng242e22b2015-05-11 10:17:43 +0200416 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000417
danilchap56036ff2016-03-22 11:14:09 -0700418 rtc::CritScope lock(&critical_section_rtcp_sender_);
xians@webrtc.org8738d272011-11-25 13:43:53 +0000419
pbosda903ea2015-10-02 02:36:56 -0700420 if (method_ == RtcpMode::kOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000421 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000422
Erik Språng242e22b2015-05-11 10:17:43 +0200423 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200424 // for video key-frames we want to send the RTCP before the large key-frame
425 // if we have a 100 ms margin
426 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
427 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000428
Erik Språng242e22b2015-05-11 10:17:43 +0200429 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200430 return true;
431 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200432 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200433 // wrap
434 return true;
435 }
436 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000437}
438
danilchap56036ff2016-03-22 11:14:09 -0700439std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSR(const RtcpContext& ctx) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200440 // Timestamp shouldn't be estimated before first media frame.
441 RTC_DCHECK_GE(last_frame_capture_time_ms_, 0);
Erik Språng61be2a42015-04-27 13:32:52 +0200442 // The timestamp of this RTCP packet should be estimated as the timestamp of
443 // the frame being captured at this moment. We are calculating that
444 // timestamp as the last frame's timestamp + the time since the last frame
445 // was captured.
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200446 uint32_t rtp_timestamp =
447 start_timestamp_ + last_rtp_timestamp_ +
448 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) *
Erik Språngf7c57762015-12-04 10:40:35 +0100449 (ctx.feedback_state_.frequency_hz / 1000);
niklase@google.com470e71d2011-07-07 08:21:25 +0000450
Erik Språngf7c57762015-12-04 10:40:35 +0100451 rtcp::SenderReport* report = new rtcp::SenderReport();
452 report->From(ssrc_);
danilchap34ed2b92016-01-18 02:43:32 -0800453 report->WithNtp(NtpTime(ctx.ntp_sec_, ctx.ntp_frac_));
Erik Språngf7c57762015-12-04 10:40:35 +0100454 report->WithRtpTimestamp(rtp_timestamp);
455 report->WithPacketCount(ctx.feedback_state_.packets_sent);
456 report->WithOctetCount(ctx.feedback_state_.media_bytes_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000457
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200458 for (auto it : report_blocks_)
Erik Språngf7c57762015-12-04 10:40:35 +0100459 report->WithReportBlock(it.second);
niklase@google.com470e71d2011-07-07 08:21:25 +0000460
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200461 report_blocks_.clear();
Erik Språngf7c57762015-12-04 10:40:35 +0100462
danilchap56036ff2016-03-22 11:14:09 -0700463 return std::unique_ptr<rtcp::RtcpPacket>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000464}
465
danilchap56036ff2016-03-22 11:14:09 -0700466std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSDES(
Erik Språngf7c57762015-12-04 10:40:35 +0100467 const RtcpContext& ctx) {
Erik Språng0ea42d32015-06-25 14:46:16 +0200468 size_t length_cname = cname_.length();
henrikg91d6ede2015-09-17 00:24:34 -0700469 RTC_CHECK_LT(length_cname, static_cast<size_t>(RTCP_CNAME_SIZE));
niklase@google.com470e71d2011-07-07 08:21:25 +0000470
Erik Språngf7c57762015-12-04 10:40:35 +0100471 rtcp::Sdes* sdes = new rtcp::Sdes();
472 sdes->WithCName(ssrc_, cname_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200473
474 for (const auto it : csrc_cnames_)
Erik Språngf7c57762015-12-04 10:40:35 +0100475 sdes->WithCName(it.first, it.second);
Erik Språng0ea42d32015-06-25 14:46:16 +0200476
danilchap56036ff2016-03-22 11:14:09 -0700477 return std::unique_ptr<rtcp::RtcpPacket>(sdes);
niklase@google.com470e71d2011-07-07 08:21:25 +0000478}
479
danilchap56036ff2016-03-22 11:14:09 -0700480std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildRR(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100481 rtcp::ReceiverReport* report = new rtcp::ReceiverReport();
482 report->From(ssrc_);
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200483 for (auto it : report_blocks_)
Erik Språngf7c57762015-12-04 10:40:35 +0100484 report->WithReportBlock(it.second);
Erik Språng61be2a42015-04-27 13:32:52 +0200485
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200486 report_blocks_.clear();
danilchap56036ff2016-03-22 11:14:09 -0700487 return std::unique_ptr<rtcp::RtcpPacket>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000488}
489
danilchap56036ff2016-03-22 11:14:09 -0700490std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildPLI(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100491 rtcp::Pli* pli = new rtcp::Pli();
492 pli->From(ssrc_);
493 pli->To(remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200494
Erik Språng242e22b2015-05-11 10:17:43 +0200495 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
496 "RTCPSender::PLI");
497 ++packet_type_counter_.pli_packets;
498 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
499 ssrc_, packet_type_counter_.pli_packets);
500
danilchap56036ff2016-03-22 11:14:09 -0700501 return std::unique_ptr<rtcp::RtcpPacket>(pli);
Erik Språng61be2a42015-04-27 13:32:52 +0200502}
503
danilchap56036ff2016-03-22 11:14:09 -0700504std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildFIR(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100505 if (!ctx.repeat_)
sprang62dae192015-08-05 02:35:35 -0700506 ++sequence_number_fir_; // Do not increase if repetition.
niklase@google.com470e71d2011-07-07 08:21:25 +0000507
Erik Språngf7c57762015-12-04 10:40:35 +0100508 rtcp::Fir* fir = new rtcp::Fir();
509 fir->From(ssrc_);
Danil Chapovalov32e590e2016-01-22 11:04:56 +0100510 fir->WithRequestTo(remote_ssrc_, sequence_number_fir_);
Erik Språng242e22b2015-05-11 10:17:43 +0200511
512 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
513 "RTCPSender::FIR");
514 ++packet_type_counter_.fir_packets;
515 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
516 ssrc_, packet_type_counter_.fir_packets);
517
danilchap56036ff2016-03-22 11:14:09 -0700518 return std::unique_ptr<rtcp::RtcpPacket>(fir);
niklase@google.com470e71d2011-07-07 08:21:25 +0000519}
520
521/*
522 0 1 2 3
523 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
524 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
525 | First | Number | PictureID |
526 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
527*/
danilchap56036ff2016-03-22 11:14:09 -0700528std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSLI(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100529 rtcp::Sli* sli = new rtcp::Sli();
530 sli->From(ssrc_);
531 sli->To(remote_ssrc_);
sprang0365a272015-08-11 01:02:37 -0700532 // Crop picture id to 6 least significant bits.
Erik Språngf7c57762015-12-04 10:40:35 +0100533 sli->WithPictureId(ctx.picture_id_ & 0x3F);
sprang0365a272015-08-11 01:02:37 -0700534
danilchap56036ff2016-03-22 11:14:09 -0700535 return std::unique_ptr<rtcp::RtcpPacket>(sli);
niklase@google.com470e71d2011-07-07 08:21:25 +0000536}
537
538/*
539 0 1 2 3
540 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
541 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
542 | PB |0| Payload Type| Native RPSI bit string |
543 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
544 | defined per codec ... | Padding (0) |
545 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
546*/
547/*
548* Note: not generic made for VP8
549*/
danilchap56036ff2016-03-22 11:14:09 -0700550std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildRPSI(
Erik Språngf7c57762015-12-04 10:40:35 +0100551 const RtcpContext& ctx) {
552 if (ctx.feedback_state_.send_payload_type == 0xFF)
553 return nullptr;
Erik Språng242e22b2015-05-11 10:17:43 +0200554
Erik Språngf7c57762015-12-04 10:40:35 +0100555 rtcp::Rpsi* rpsi = new rtcp::Rpsi();
556 rpsi->From(ssrc_);
557 rpsi->To(remote_ssrc_);
558 rpsi->WithPayloadType(ctx.feedback_state_.send_payload_type);
559 rpsi->WithPictureId(ctx.picture_id_);
sprangcf7f54d2015-08-13 04:37:42 -0700560
danilchap56036ff2016-03-22 11:14:09 -0700561 return std::unique_ptr<rtcp::RtcpPacket>(rpsi);
niklase@google.com470e71d2011-07-07 08:21:25 +0000562}
563
danilchap56036ff2016-03-22 11:14:09 -0700564std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildREMB(
Erik Språngf7c57762015-12-04 10:40:35 +0100565 const RtcpContext& ctx) {
566 rtcp::Remb* remb = new rtcp::Remb();
567 remb->From(ssrc_);
sprangdd4edc52015-08-21 04:21:51 -0700568 for (uint32_t ssrc : remb_ssrcs_)
Erik Språngf7c57762015-12-04 10:40:35 +0100569 remb->AppliesTo(ssrc);
570 remb->WithBitrateBps(remb_bitrate_);
Erik Språng61be2a42015-04-27 13:32:52 +0200571
Erik Språng242e22b2015-05-11 10:17:43 +0200572 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
573 "RTCPSender::REMB");
574
danilchap56036ff2016-03-22 11:14:09 -0700575 return std::unique_ptr<rtcp::RtcpPacket>(remb);
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000576}
577
Erik Språng61be2a42015-04-27 13:32:52 +0200578void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
danilchap56036ff2016-03-22 11:14:09 -0700579 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200580 tmmbr_send_ = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000581}
582
danilchap56036ff2016-03-22 11:14:09 -0700583std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBR(
Erik Språngf7c57762015-12-04 10:40:35 +0100584 const RtcpContext& ctx) {
585 if (ctx.feedback_state_.module == nullptr)
586 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200587 // Before sending the TMMBR check the received TMMBN, only an owner is
588 // allowed to raise the bitrate:
589 // * If the sender is an owner of the TMMBN -> send TMMBR
590 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000591
danilchap13deaad2016-05-24 13:25:27 -0700592 TMMBRHelp tmmbr_help;
Erik Språng61be2a42015-04-27 13:32:52 +0200593 // get current bounding set from RTCP receiver
594 bool tmmbrOwner = false;
595 // store in candidateSet, allocates one extra slot
danilchap13deaad2016-05-24 13:25:27 -0700596 TMMBRSet* candidateSet = tmmbr_help.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000597
Erik Språng242e22b2015-05-11 10:17:43 +0200598 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
599 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
Erik Språng61be2a42015-04-27 13:32:52 +0200600 // since RTCPreceiver is not doing the reverse we should be fine
601 int32_t lengthOfBoundingSet =
danilchap6db6cdc2015-12-15 02:54:47 -0800602 ctx.feedback_state_.module->BoundingSet(&tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +0000603
Erik Språng61be2a42015-04-27 13:32:52 +0200604 if (lengthOfBoundingSet > 0) {
605 for (int32_t i = 0; i < lengthOfBoundingSet; i++) {
Erik Språng242e22b2015-05-11 10:17:43 +0200606 if (candidateSet->Tmmbr(i) == tmmbr_send_ &&
607 candidateSet->PacketOH(i) == packet_oh_send_) {
Erik Språngf7c57762015-12-04 10:40:35 +0100608 // Do not send the same tuple.
609 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200610 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000611 }
Erik Språng61be2a42015-04-27 13:32:52 +0200612 if (!tmmbrOwner) {
613 // use received bounding set as candidate set
614 // add current tuple
Erik Språng242e22b2015-05-11 10:17:43 +0200615 candidateSet->SetEntry(lengthOfBoundingSet, tmmbr_send_, packet_oh_send_,
616 ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200617 int numCandidates = lengthOfBoundingSet + 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000618
Erik Språng61be2a42015-04-27 13:32:52 +0200619 // find bounding set
Erik Språngf7c57762015-12-04 10:40:35 +0100620 TMMBRSet* boundingSet = nullptr;
danilchap13deaad2016-05-24 13:25:27 -0700621 int numBoundingSet = tmmbr_help.FindTMMBRBoundingSet(boundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200622 if (numBoundingSet > 0 || numBoundingSet <= numCandidates)
danilchap13deaad2016-05-24 13:25:27 -0700623 tmmbrOwner = tmmbr_help.IsOwner(ssrc_, numBoundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200624 if (!tmmbrOwner) {
Erik Språngf7c57762015-12-04 10:40:35 +0100625 // Did not enter bounding set, no meaning to send this request.
626 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200627 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000628 }
Erik Språng61be2a42015-04-27 13:32:52 +0200629 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000630
Erik Språngf7c57762015-12-04 10:40:35 +0100631 if (!tmmbr_send_)
632 return nullptr;
sprang81a3e602015-08-21 05:30:11 -0700633
Erik Språngf7c57762015-12-04 10:40:35 +0100634 rtcp::Tmmbr* tmmbr = new rtcp::Tmmbr();
635 tmmbr->From(ssrc_);
danilchapf174e3a2016-02-05 04:56:36 -0800636 rtcp::TmmbItem request;
637 request.set_ssrc(remote_ssrc_);
638 request.set_bitrate_bps(tmmbr_send_ * 1000);
639 request.set_packet_overhead(packet_oh_send_);
640 tmmbr->WithTmmbr(request);
Erik Språngf7c57762015-12-04 10:40:35 +0100641
danilchap56036ff2016-03-22 11:14:09 -0700642 return std::unique_ptr<rtcp::RtcpPacket>(tmmbr);
Erik Språng61be2a42015-04-27 13:32:52 +0200643}
644
danilchap56036ff2016-03-22 11:14:09 -0700645std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBN(
Erik Språngf7c57762015-12-04 10:40:35 +0100646 const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100647 rtcp::Tmmbn* tmmbn = new rtcp::Tmmbn();
648 tmmbn->From(ssrc_);
danilchap6eaa3a42016-05-09 10:59:50 -0700649 for (const rtcp::TmmbItem& tmmbr : tmmbn_to_send_) {
650 if (tmmbr.bitrate_bps() > 0) {
651 tmmbn->WithTmmbr(tmmbr);
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000652 }
Erik Språng61be2a42015-04-27 13:32:52 +0200653 }
sprangd83df502015-08-27 01:05:08 -0700654
danilchap56036ff2016-03-22 11:14:09 -0700655 return std::unique_ptr<rtcp::RtcpPacket>(tmmbn);
niklase@google.com470e71d2011-07-07 08:21:25 +0000656}
657
danilchap56036ff2016-03-22 11:14:09 -0700658std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildAPP(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100659 rtcp::App* app = new rtcp::App();
660 app->From(ssrc_);
661 app->WithSubType(app_sub_type_);
662 app->WithName(app_name_);
663 app->WithData(app_data_.get(), app_length_);
Erik Språng521875a2015-09-01 10:11:16 +0200664
danilchap56036ff2016-03-22 11:14:09 -0700665 return std::unique_ptr<rtcp::RtcpPacket>(app);
Erik Språng61be2a42015-04-27 13:32:52 +0200666}
667
danilchap56036ff2016-03-22 11:14:09 -0700668std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildNACK(
Erik Språngf7c57762015-12-04 10:40:35 +0100669 const RtcpContext& ctx) {
670 rtcp::Nack* nack = new rtcp::Nack();
671 nack->From(ssrc_);
672 nack->To(remote_ssrc_);
673 nack->WithList(ctx.nack_list_, ctx.nack_size_);
Erik Språng61be2a42015-04-27 13:32:52 +0200674
675 // Report stats.
676 NACKStringBuilder stringBuilder;
Erik Språngf7c57762015-12-04 10:40:35 +0100677 for (int idx = 0; idx < ctx.nack_size_; ++idx) {
678 stringBuilder.PushNACK(ctx.nack_list_[idx]);
679 nack_stats_.ReportRequest(ctx.nack_list_[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +0200680 }
Erik Språng61be2a42015-04-27 13:32:52 +0200681 packet_type_counter_.nack_requests = nack_stats_.requests();
682 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +0200683
684 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
685 "RTCPSender::NACK", "nacks",
686 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
687 ++packet_type_counter_.nack_packets;
688 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
689 ssrc_, packet_type_counter_.nack_packets);
690
danilchap56036ff2016-03-22 11:14:09 -0700691 return std::unique_ptr<rtcp::RtcpPacket>(nack);
Erik Språng61be2a42015-04-27 13:32:52 +0200692}
693
danilchap56036ff2016-03-22 11:14:09 -0700694std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildBYE(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100695 rtcp::Bye* bye = new rtcp::Bye();
696 bye->From(ssrc_);
sprangd8ee4f92015-08-24 03:25:19 -0700697 for (uint32_t csrc : csrcs_)
Erik Språngf7c57762015-12-04 10:40:35 +0100698 bye->WithCsrc(csrc);
sprangd8ee4f92015-08-24 03:25:19 -0700699
danilchap56036ff2016-03-22 11:14:09 -0700700 return std::unique_ptr<rtcp::RtcpPacket>(bye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000701}
702
danilchap56036ff2016-03-22 11:14:09 -0700703std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildReceiverReferenceTime(
Erik Språngf7c57762015-12-04 10:40:35 +0100704 const RtcpContext& ctx) {
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000705
Danil Chapovalov256e5b22016-01-15 14:16:24 +0100706 rtcp::ExtendedReports* xr = new rtcp::ExtendedReports();
Erik Språngf7c57762015-12-04 10:40:35 +0100707 xr->From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000708
Erik Språngca28fdc2015-08-31 14:00:50 +0200709 rtcp::Rrtr rrtr;
Danil Chapovalovfc47ed62015-12-07 14:46:35 +0100710 rrtr.WithNtp(NtpTime(ctx.ntp_sec_, ctx.ntp_frac_));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000711
danilchapde138822016-01-29 11:26:14 -0800712 xr->WithRrtr(rrtr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000713
Erik Språngca28fdc2015-08-31 14:00:50 +0200714 // TODO(sprang): Merge XR report sending to contain all of RRTR, DLRR, VOIP?
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000715
danilchap56036ff2016-03-22 11:14:09 -0700716 return std::unique_ptr<rtcp::RtcpPacket>(xr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000717}
718
danilchap56036ff2016-03-22 11:14:09 -0700719std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildDlrr(
Erik Språngf7c57762015-12-04 10:40:35 +0100720 const RtcpContext& ctx) {
Danil Chapovalov256e5b22016-01-15 14:16:24 +0100721 rtcp::ExtendedReports* xr = new rtcp::ExtendedReports();
Erik Språngf7c57762015-12-04 10:40:35 +0100722 xr->From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000723
Erik Språngca28fdc2015-08-31 14:00:50 +0200724 rtcp::Dlrr dlrr;
Erik Språngf7c57762015-12-04 10:40:35 +0100725 const RtcpReceiveTimeInfo& info = ctx.feedback_state_.last_xr_rr;
Erik Språngca28fdc2015-08-31 14:00:50 +0200726 dlrr.WithDlrrItem(info.sourceSSRC, info.lastRR, info.delaySinceLastRR);
727
danilchapde138822016-01-29 11:26:14 -0800728 xr->WithDlrr(dlrr);
Erik Språngca28fdc2015-08-31 14:00:50 +0200729
danilchap56036ff2016-03-22 11:14:09 -0700730 return std::unique_ptr<rtcp::RtcpPacket>(xr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000731}
732
Erik Språng242e22b2015-05-11 10:17:43 +0200733// TODO(sprang): Add a unit test for this, or remove if the code isn't used.
danilchap56036ff2016-03-22 11:14:09 -0700734std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildVoIPMetric(
Erik Språngf7c57762015-12-04 10:40:35 +0100735 const RtcpContext& context) {
Danil Chapovalov256e5b22016-01-15 14:16:24 +0100736 rtcp::ExtendedReports* xr = new rtcp::ExtendedReports();
Erik Språngf7c57762015-12-04 10:40:35 +0100737 xr->From(ssrc_);
Erik Språngca28fdc2015-08-31 14:00:50 +0200738
739 rtcp::VoipMetric voip;
740 voip.To(remote_ssrc_);
danilchap91941ae2015-12-15 07:06:36 -0800741 voip.WithVoipMetric(xr_voip_metric_);
Erik Språngca28fdc2015-08-31 14:00:50 +0200742
danilchapde138822016-01-29 11:26:14 -0800743 xr->WithVoipMetric(voip);
Erik Språngca28fdc2015-08-31 14:00:50 +0200744
danilchap56036ff2016-03-22 11:14:09 -0700745 return std::unique_ptr<rtcp::RtcpPacket>(xr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000746}
747
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000748int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200749 RTCPPacketType packetType,
750 int32_t nack_size,
751 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000752 bool repeat,
753 uint64_t pictureID) {
Erik Språng242e22b2015-05-11 10:17:43 +0200754 return SendCompoundRTCP(
755 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
756 nack_size, nack_list, repeat, pictureID);
757}
758
759int32_t RTCPSender::SendCompoundRTCP(
760 const FeedbackState& feedback_state,
Erik Språngf7c57762015-12-04 10:40:35 +0100761 const std::set<RTCPPacketType>& packet_types,
Erik Språng242e22b2015-05-11 10:17:43 +0200762 int32_t nack_size,
763 const uint16_t* nack_list,
764 bool repeat,
765 uint64_t pictureID) {
terelius429c3452016-01-21 05:42:04 -0800766 PacketContainer container(transport_, event_log_);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000767 {
danilchap56036ff2016-03-22 11:14:09 -0700768 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbosda903ea2015-10-02 02:36:56 -0700769 if (method_ == RtcpMode::kOff) {
Erik Språng61be2a42015-04-27 13:32:52 +0200770 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
771 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +0000772 }
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200773 // Add all flags as volatile. Non volatile entries will not be overwritten.
774 // All new volatile flags added will be consumed by the end of this call.
775 SetFlags(packet_types, true);
776
777 // Prevent sending streams to send SR before any media has been sent.
778 const bool can_calculate_rtp_timestamp = (last_frame_capture_time_ms_ >= 0);
779 if (!can_calculate_rtp_timestamp) {
780 bool consumed_sr_flag = ConsumeFlag(kRtcpSr);
781 bool consumed_report_flag = sending_ && ConsumeFlag(kRtcpReport);
782 bool sender_report = consumed_report_flag || consumed_sr_flag;
783 if (sender_report && AllVolatileFlagsConsumed()) {
784 // This call was for Sender Report and nothing else.
785 return 0;
786 }
787 if (sending_ && method_ == RtcpMode::kCompound) {
788 // Not allowed to send any RTCP packet without sender report.
789 return -1;
790 }
791 }
792
793 if (packet_type_counter_.first_packet_time_ms == -1)
794 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språngf7c57762015-12-04 10:40:35 +0100795
796 // We need to send our NTP even if we haven't received any reports.
797 uint32_t ntp_sec;
798 uint32_t ntp_frac;
799 clock_->CurrentNtp(ntp_sec, ntp_frac);
800 RtcpContext context(feedback_state, nack_size, nack_list, repeat, pictureID,
danilchap56036ff2016-03-22 11:14:09 -0700801 ntp_sec, ntp_frac);
Erik Språngf7c57762015-12-04 10:40:35 +0100802
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200803 PrepareReport(feedback_state);
Erik Språngf7c57762015-12-04 10:40:35 +0100804
danilchap56036ff2016-03-22 11:14:09 -0700805 std::unique_ptr<rtcp::RtcpPacket> packet_bye;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800806
Erik Språngf7c57762015-12-04 10:40:35 +0100807 auto it = report_flags_.begin();
808 while (it != report_flags_.end()) {
809 auto builder_it = builders_.find(it->type);
810 RTC_DCHECK(builder_it != builders_.end());
811 if (it->is_volatile) {
812 report_flags_.erase(it++);
813 } else {
814 ++it;
815 }
816
817 BuilderFunc func = builder_it->second;
danilchap56036ff2016-03-22 11:14:09 -0700818 std::unique_ptr<rtcp::RtcpPacket> packet = (this->*func)(context);
Erik Språngf7c57762015-12-04 10:40:35 +0100819 if (packet.get() == nullptr)
820 return -1;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800821 // If there is a BYE, don't append now - save it and append it
822 // at the end later.
823 if (builder_it->first == kRtcpBye) {
824 packet_bye = std::move(packet);
825 } else {
826 container.Append(packet.release());
827 }
828 }
829
830 // Append the BYE now at the end
831 if (packet_bye) {
832 container.Append(packet_bye.release());
Erik Språngf7c57762015-12-04 10:40:35 +0100833 }
834
835 if (packet_type_counter_observer_ != nullptr) {
836 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
837 remote_ssrc_, packet_type_counter_);
838 }
839
840 RTC_DCHECK(AllVolatileFlagsConsumed());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000841 }
Erik Språng61be2a42015-04-27 13:32:52 +0200842
danilchap41befce2016-03-30 11:11:51 -0700843 size_t bytes_sent = container.SendPackets(max_payload_length_);
Erik Språngf7c57762015-12-04 10:40:35 +0100844 return bytes_sent == 0 ? -1 : 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000845}
846
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200847void RTCPSender::PrepareReport(const FeedbackState& feedback_state) {
Erik Språng242e22b2015-05-11 10:17:43 +0200848 bool generate_report;
849 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
850 // Report type already explicitly set, don't automatically populate.
851 generate_report = true;
henrikg91d6ede2015-09-17 00:24:34 -0700852 RTC_DCHECK(ConsumeFlag(kRtcpReport) == false);
Erik Språng242e22b2015-05-11 10:17:43 +0200853 } else {
854 generate_report =
pbosda903ea2015-10-02 02:36:56 -0700855 (ConsumeFlag(kRtcpReport) && method_ == RtcpMode::kReducedSize) ||
856 method_ == RtcpMode::kCompound;
Erik Språng242e22b2015-05-11 10:17:43 +0200857 if (generate_report)
858 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000859 }
860
Erik Språng0ea42d32015-06-25 14:46:16 +0200861 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
Erik Språng242e22b2015-05-11 10:17:43 +0200862 SetFlag(kRtcpSdes, true);
863
Erik Språng242e22b2015-05-11 10:17:43 +0200864 if (generate_report) {
865 if (!sending_ && xr_send_receiver_reference_time_enabled_)
866 SetFlag(kRtcpXrReceiverReferenceTime, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200867 if (feedback_state.has_last_xr_rr)
Erik Språng242e22b2015-05-11 10:17:43 +0200868 SetFlag(kRtcpXrDlrrReportBlock, true);
869
870 // generate next time to send an RTCP report
danilchap47a740b2015-12-15 00:30:07 -0800871 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000872
danilchap47a740b2015-12-15 00:30:07 -0800873 if (!audio_) {
Erik Språng242e22b2015-05-11 10:17:43 +0200874 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200875 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
876 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
877 if (send_bitrate_kbit != 0)
878 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000879 }
Erik Språng61be2a42015-04-27 13:32:52 +0200880 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
881 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
Erik Språng61be2a42015-04-27 13:32:52 +0200882 }
danilchap47a740b2015-12-15 00:30:07 -0800883 // The interval between RTCP packets is varied randomly over the
884 // range [1/2,3/2] times the calculated interval.
885 uint32_t timeToNext =
886 random_.Rand(minIntervalMs * 1 / 2, minIntervalMs * 3 / 2);
Erik Språng242e22b2015-05-11 10:17:43 +0200887 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000888
Per83d09102016-04-15 14:59:13 +0200889 if (receive_statistics_) {
890 StatisticianMap statisticians =
891 receive_statistics_->GetActiveStatisticians();
892 RTC_DCHECK(report_blocks_.empty());
893 for (auto& it : statisticians) {
894 AddReportBlock(feedback_state, it.first, it.second);
895 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000896 }
897 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000898}
899
danilchapa72e7342015-12-22 08:07:45 -0800900bool RTCPSender::AddReportBlock(const FeedbackState& feedback_state,
901 uint32_t ssrc,
902 StreamStatistician* statistician) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000903 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000904 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000905 if (!statistician->GetStatistics(&stats, true))
906 return false;
danilchapa72e7342015-12-22 08:07:45 -0800907
908 if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) {
909 LOG(LS_WARNING) << "Too many report blocks.";
910 return false;
911 }
912 RTC_DCHECK(report_blocks_.find(ssrc) == report_blocks_.end());
913 rtcp::ReportBlock* block = &report_blocks_[ssrc];
914 block->To(ssrc);
915 block->WithFractionLost(stats.fraction_lost);
916 if (!block->WithCumulativeLost(stats.cumulative_lost)) {
917 report_blocks_.erase(ssrc);
918 LOG(LS_WARNING) << "Cumulative lost is oversized.";
919 return false;
920 }
921 block->WithExtHighestSeqNum(stats.extended_max_sequence_number);
922 block->WithJitter(stats.jitter);
923 block->WithLastSr(feedback_state.remote_sr);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000924
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200925 // TODO(sprang): Do we really need separate time stamps for each report?
926 // Get our NTP as late as possible to avoid a race.
927 uint32_t ntp_secs;
928 uint32_t ntp_frac;
929 clock_->CurrentNtp(ntp_secs, ntp_frac);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000930
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200931 // Delay since last received report.
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000932 if ((feedback_state.last_rr_ntp_secs != 0) ||
933 (feedback_state.last_rr_ntp_frac != 0)) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200934 // Get the 16 lowest bits of seconds and the 16 highest bits of fractions.
935 uint32_t now = ntp_secs & 0x0000FFFF;
Erik Språng61be2a42015-04-27 13:32:52 +0200936 now <<= 16;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200937 now += (ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000938
Erik Språng61be2a42015-04-27 13:32:52 +0200939 uint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
940 receiveTime <<= 16;
941 receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000942
danilchapa72e7342015-12-22 08:07:45 -0800943 block->WithDelayLastSr(now - receiveTime);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000944 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000945 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000946}
947
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000948void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
danilchap56036ff2016-03-22 11:14:09 -0700949 RTC_DCHECK_LE(csrcs.size(), static_cast<size_t>(kRtpCsrcSize));
950 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000951 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +0000952}
953
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000954int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
955 uint32_t name,
956 const uint8_t* data,
957 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +0200958 if (length % 4 != 0) {
959 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
960 return -1;
961 }
danilchap56036ff2016-03-22 11:14:09 -0700962 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000963
Erik Språng242e22b2015-05-11 10:17:43 +0200964 SetFlag(kRtcpApp, true);
965 app_sub_type_ = subType;
966 app_name_ = name;
967 app_data_.reset(new uint8_t[length]);
968 app_length_ = length;
969 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +0200970 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000971}
972
Erik Språng61be2a42015-04-27 13:32:52 +0200973int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
danilchap56036ff2016-03-22 11:14:09 -0700974 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200975 memcpy(&xr_voip_metric_, VoIPMetric, sizeof(RTCPVoIPMetric));
niklase@google.com470e71d2011-07-07 08:21:25 +0000976
Erik Språng242e22b2015-05-11 10:17:43 +0200977 SetFlag(kRtcpXrVoipMetric, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200978 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000979}
980
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000981void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700982 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200983 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000984}
985
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000986bool RTCPSender::RtcpXrReceiverReferenceTime() const {
danilchap56036ff2016-03-22 11:14:09 -0700987 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200988 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000989}
990
niklase@google.com470e71d2011-07-07 08:21:25 +0000991// no callbacks allowed inside this function
danilchap6eaa3a42016-05-09 10:59:50 -0700992void RTCPSender::SetTMMBN(const std::vector<rtcp::TmmbItem>* bounding_set) {
danilchap56036ff2016-03-22 11:14:09 -0700993 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap6eaa3a42016-05-09 10:59:50 -0700994 if (bounding_set) {
995 tmmbn_to_send_ = *bounding_set;
996 } else {
997 tmmbn_to_send_.clear();
Erik Språng61be2a42015-04-27 13:32:52 +0200998 }
danilchap6eaa3a42016-05-09 10:59:50 -0700999 SetFlag(kRtcpTmmbn, true);
niklase@google.com470e71d2011-07-07 08:21:25 +00001000}
Erik Språng61be2a42015-04-27 13:32:52 +02001001
Erik Språng242e22b2015-05-11 10:17:43 +02001002void RTCPSender::SetFlag(RTCPPacketType type, bool is_volatile) {
1003 report_flags_.insert(ReportFlag(type, is_volatile));
1004}
1005
1006void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
1007 bool is_volatile) {
1008 for (RTCPPacketType type : types)
1009 SetFlag(type, is_volatile);
1010}
1011
1012bool RTCPSender::IsFlagPresent(RTCPPacketType type) const {
1013 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
1014}
1015
1016bool RTCPSender::ConsumeFlag(RTCPPacketType type, bool forced) {
1017 auto it = report_flags_.find(ReportFlag(type, false));
1018 if (it == report_flags_.end())
1019 return false;
1020 if (it->is_volatile || forced)
1021 report_flags_.erase((it));
1022 return true;
1023}
1024
1025bool RTCPSender::AllVolatileFlagsConsumed() const {
1026 for (const ReportFlag& flag : report_flags_) {
1027 if (flag.is_volatile)
1028 return false;
1029 }
1030 return true;
1031}
1032
sprang233bd872015-09-08 13:25:16 -07001033bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
sprang233bd872015-09-08 13:25:16 -07001034 class Sender : public rtcp::RtcpPacket::PacketReadyCallback {
1035 public:
terelius429c3452016-01-21 05:42:04 -08001036 Sender(Transport* transport, RtcEventLog* event_log)
1037 : transport_(transport), event_log_(event_log), send_failure_(false) {}
sprang233bd872015-09-08 13:25:16 -07001038
1039 void OnPacketReady(uint8_t* data, size_t length) override {
terelius429c3452016-01-21 05:42:04 -08001040 if (transport_->SendRtcp(data, length)) {
1041 if (event_log_) {
1042 event_log_->LogRtcpPacket(kOutgoingPacket, MediaType::ANY, data,
1043 length);
1044 }
1045 } else {
sprang233bd872015-09-08 13:25:16 -07001046 send_failure_ = true;
terelius429c3452016-01-21 05:42:04 -08001047 }
sprang233bd872015-09-08 13:25:16 -07001048 }
1049
1050 Transport* const transport_;
terelius429c3452016-01-21 05:42:04 -08001051 RtcEventLog* const event_log_;
sprang233bd872015-09-08 13:25:16 -07001052 bool send_failure_;
terelius429c3452016-01-21 05:42:04 -08001053 // TODO(terelius): We would like to
1054 // RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(Sender);
1055 // but we can't because of an incorrect warning (C4822) in MVS 2013.
1056 } sender(transport_, event_log_);
sprang233bd872015-09-08 13:25:16 -07001057
danilchap41befce2016-03-30 11:11:51 -07001058 RTC_DCHECK_LE(max_payload_length_, static_cast<size_t>(IP_PACKET_SIZE));
sprang233bd872015-09-08 13:25:16 -07001059 uint8_t buffer[IP_PACKET_SIZE];
danilchap41befce2016-03-30 11:11:51 -07001060 return packet.BuildExternalBuffer(buffer, max_payload_length_, &sender) &&
sprang233bd872015-09-08 13:25:16 -07001061 !sender.send_failure_;
1062}
1063
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001064} // namespace webrtc