blob: bf7d24f320606f73b6fc531b543fee3bddb7039c [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
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000013#include <assert.h> // assert
stefan@webrtc.org9354cc92012-06-07 08:10:14 +000014#include <string.h> // memcpy
niklase@google.com470e71d2011-07-07 08:21:25 +000015
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000016#include <algorithm> // min
Erik Språng61be2a42015-04-27 13:32:52 +020017#include <limits> // max
danilchapb8b6fbb2015-12-10 05:05:27 -080018#include <utility>
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000019
Erik Språng61be2a42015-04-27 13:32:52 +020020#include "webrtc/base/checks.h"
Peter Boströmebc0b4e2015-10-28 16:39:33 +010021#include "webrtc/base/logging.h"
tommie4f96502015-10-20 23:00:48 -070022#include "webrtc/base/trace_event.h"
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000023#include "webrtc/common_types.h"
sprang@webrtc.org779c3d12015-03-17 16:42:49 +000024#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
danilchap0219c9b2015-11-18 05:56:53 -080025#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/app.h"
danilchap50c51362015-11-22 09:03:11 -080026#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/bye.h"
danilchap2f7dea12016-01-13 02:03:04 -080027#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/compound_packet.h"
Danil Chapovalov256e5b22016-01-15 14:16:24 +010028#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_reports.h"
Danil Chapovalov5679da12016-01-15 13:19:53 +010029#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/fir.h"
danilchapa8890a52015-12-22 03:43:04 -080030#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/nack.h"
danilchapf8385ad2015-11-27 05:36:09 -080031#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/pli.h"
Danil Chapovalov97f7e132015-12-04 16:13:30 +010032#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
Danil Chapovalova5eba6c2016-01-15 12:40:15 +010033#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/remb.h"
Danil Chapovalov2c132972016-01-15 15:21:21 +010034#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rpsi.h"
danilchap92e677a2016-01-12 10:04:52 -080035#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sli.h"
danilchapef3d8052016-01-11 03:31:08 -080036#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbn.h"
danilchap7e8145f2016-01-11 11:49:19 -080037#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbr.h"
sprang233bd872015-09-08 13:25:16 -070038#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
tommie4f96502015-10-20 23:00:48 -070039#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010040#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000041
niklase@google.com470e71d2011-07-07 08:21:25 +000042namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000043
44using RTCPUtility::RTCPCnameInformation;
45
Erik Språng61be2a42015-04-27 13:32:52 +020046NACKStringBuilder::NACKStringBuilder()
danilchap162abd32015-12-10 02:39:40 -080047 : stream_(""), count_(0), prevNack_(0), consecutive_(false) {}
edjee@google.com79b02892013-04-04 19:43:34 +000048
pbos@webrtc.orgf3e4cee2013-07-31 15:17:19 +000049NACKStringBuilder::~NACKStringBuilder() {}
50
danilchap162abd32015-12-10 02:39:40 -080051void NACKStringBuilder::PushNACK(uint16_t nack) {
Erik Språng242e22b2015-05-11 10:17:43 +020052 if (count_ == 0) {
53 stream_ << nack;
54 } else if (nack == prevNack_ + 1) {
55 consecutive_ = true;
Erik Språng61be2a42015-04-27 13:32:52 +020056 } else {
Erik Språng242e22b2015-05-11 10:17:43 +020057 if (consecutive_) {
58 stream_ << "-" << prevNack_;
59 consecutive_ = false;
edjee@google.com79b02892013-04-04 19:43:34 +000060 }
Erik Språng242e22b2015-05-11 10:17:43 +020061 stream_ << "," << nack;
Erik Språng61be2a42015-04-27 13:32:52 +020062 }
Erik Språng242e22b2015-05-11 10:17:43 +020063 count_++;
64 prevNack_ = nack;
edjee@google.com79b02892013-04-04 19:43:34 +000065}
66
Erik Språng61be2a42015-04-27 13:32:52 +020067std::string NACKStringBuilder::GetResult() {
Erik Språng242e22b2015-05-11 10:17:43 +020068 if (consecutive_) {
69 stream_ << "-" << prevNack_;
70 consecutive_ = false;
Erik Språng61be2a42015-04-27 13:32:52 +020071 }
Erik Språng242e22b2015-05-11 10:17:43 +020072 return stream_.str();
edjee@google.com79b02892013-04-04 19:43:34 +000073}
74
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000075RTCPSender::FeedbackState::FeedbackState()
76 : send_payload_type(0),
77 frequency_hz(0),
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +000078 packets_sent(0),
79 media_bytes_sent(0),
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000080 send_bitrate(0),
81 last_rr_ntp_secs(0),
82 last_rr_ntp_frac(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000083 remote_sr(0),
Erik Språng61be2a42015-04-27 13:32:52 +020084 has_last_xr_rr(false),
danilchap162abd32015-12-10 02:39:40 -080085 module(nullptr) {}
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000086
danilchap2f7dea12016-01-13 02:03:04 -080087class PacketContainer : public rtcp::CompoundPacket,
Erik Språngf7c57762015-12-04 10:40:35 +010088 public rtcp::RtcpPacket::PacketReadyCallback {
89 public:
90 explicit PacketContainer(Transport* transport)
91 : transport_(transport), bytes_sent_(0) {}
92 virtual ~PacketContainer() {
93 for (RtcpPacket* packet : appended_packets_)
94 delete packet;
95 }
96
97 void OnPacketReady(uint8_t* data, size_t length) override {
98 if (transport_->SendRtcp(data, length))
99 bytes_sent_ += length;
100 }
101
102 size_t SendPackets() {
danilchap2f7dea12016-01-13 02:03:04 -0800103 rtcp::CompoundPacket::Build(this);
Erik Språngf7c57762015-12-04 10:40:35 +0100104 return bytes_sent_;
105 }
106
107 private:
108 Transport* transport_;
109 size_t bytes_sent_;
110};
111
112class RTCPSender::RtcpContext {
113 public:
Erik Språng242e22b2015-05-11 10:17:43 +0200114 RtcpContext(const FeedbackState& feedback_state,
115 int32_t nack_size,
116 const uint16_t* nack_list,
117 bool repeat,
118 uint64_t picture_id,
Erik Språngf7c57762015-12-04 10:40:35 +0100119 uint32_t ntp_sec,
120 uint32_t ntp_frac,
121 PacketContainer* container)
122 : feedback_state_(feedback_state),
123 nack_size_(nack_size),
124 nack_list_(nack_list),
125 repeat_(repeat),
126 picture_id_(picture_id),
127 ntp_sec_(ntp_sec),
128 ntp_frac_(ntp_frac),
129 container_(container) {}
Erik Språng242e22b2015-05-11 10:17:43 +0200130
Erik Språngf7c57762015-12-04 10:40:35 +0100131 virtual ~RtcpContext() {}
Erik Språng242e22b2015-05-11 10:17:43 +0200132
Erik Språngf7c57762015-12-04 10:40:35 +0100133 const FeedbackState& feedback_state_;
134 const int32_t nack_size_;
135 const uint16_t* nack_list_;
136 const bool repeat_;
137 const uint64_t picture_id_;
138 const uint32_t ntp_sec_;
139 const uint32_t ntp_frac_;
Erik Språng242e22b2015-05-11 10:17:43 +0200140
Erik Språngf7c57762015-12-04 10:40:35 +0100141 PacketContainer* const container_;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200142};
143
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000144RTCPSender::RTCPSender(
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000145 bool audio,
146 Clock* clock,
147 ReceiveStatistics* receive_statistics,
sprang86fd9ed2015-09-29 04:45:43 -0700148 RtcpPacketTypeCounterObserver* packet_type_counter_observer,
149 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),
sprang86fd9ed2015-09-29 04:45:43 -0700154 transport_(outgoing_transport),
niklase@google.com470e71d2011-07-07 08:21:25 +0000155
Erik Språng242e22b2015-05-11 10:17:43 +0200156 critical_section_rtcp_sender_(
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000157 CriticalSectionWrapper::CreateCriticalSection()),
Erik Språng242e22b2015-05-11 10:17:43 +0200158 using_nack_(false),
159 sending_(false),
160 remb_enabled_(false),
Erik Språng242e22b2015-05-11 10:17:43 +0200161 next_time_to_send_rtcp_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000162 start_timestamp_(0),
163 last_rtp_timestamp_(0),
164 last_frame_capture_time_ms_(-1),
Erik Språng242e22b2015-05-11 10:17:43 +0200165 ssrc_(0),
166 remote_ssrc_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000167 receive_statistics_(receive_statistics),
niklase@google.com470e71d2011-07-07 08:21:25 +0000168
Erik Språng242e22b2015-05-11 10:17:43 +0200169 sequence_number_fir_(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000170
Erik Språng242e22b2015-05-11 10:17:43 +0200171 remb_bitrate_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000172
Erik Språng242e22b2015-05-11 10:17:43 +0200173 tmmbr_help_(),
174 tmmbr_send_(0),
175 packet_oh_send_(0),
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000176
Erik Språng242e22b2015-05-11 10:17:43 +0200177 app_sub_type_(0),
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200178 app_name_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200179 app_data_(nullptr),
180 app_length_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000181
Erik Språng242e22b2015-05-11 10:17:43 +0200182 xr_send_receiver_reference_time_enabled_(false),
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000183 packet_type_counter_observer_(packet_type_counter_observer) {
Erik Språng242e22b2015-05-11 10:17:43 +0200184 memset(last_send_report_, 0, sizeof(last_send_report_));
185 memset(last_rtcp_time_, 0, sizeof(last_rtcp_time_));
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 {
Erik Språng242e22b2015-05-11 10:17:43 +0200210 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
211 return method_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000212}
213
pbosda903ea2015-10-02 02:36:56 -0700214void RTCPSender::SetRTCPStatus(RtcpMode method) {
Erik Språng242e22b2015-05-11 10:17:43 +0200215 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
216 method_ = method;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000217
pbosda903ea2015-10-02 02:36:56 -0700218 if (method == RtcpMode::kOff)
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000219 return;
Erik Språng242e22b2015-05-11 10:17:43 +0200220 next_time_to_send_rtcp_ =
221 clock_->TimeInMilliseconds() +
222 (audio_ ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000223}
224
Erik Språng61be2a42015-04-27 13:32:52 +0200225bool RTCPSender::Sending() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200226 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
227 return sending_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000228}
229
Erik Språng61be2a42015-04-27 13:32:52 +0200230int32_t RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
231 bool sending) {
232 bool sendRTCPBye = false;
233 {
Erik Språng242e22b2015-05-11 10:17:43 +0200234 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000235
pbosda903ea2015-10-02 02:36:56 -0700236 if (method_ != RtcpMode::kOff) {
Erik Språng242e22b2015-05-11 10:17:43 +0200237 if (sending == false && sending_ == true) {
Erik Språng61be2a42015-04-27 13:32:52 +0200238 // Trigger RTCP bye
239 sendRTCPBye = true;
240 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000241 }
Erik Språng242e22b2015-05-11 10:17:43 +0200242 sending_ = sending;
Erik Språng61be2a42015-04-27 13:32:52 +0200243 }
244 if (sendRTCPBye)
245 return SendRTCP(feedback_state, kRtcpBye);
246 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000247}
248
Erik Språng61be2a42015-04-27 13:32:52 +0200249bool RTCPSender::REMB() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200250 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
251 return remb_enabled_;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000252}
253
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000254void RTCPSender::SetREMBStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200255 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
256 remb_enabled_ = enable;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000257}
258
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000259void RTCPSender::SetREMBData(uint32_t bitrate,
260 const std::vector<uint32_t>& ssrcs) {
Erik Språng242e22b2015-05-11 10:17:43 +0200261 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
262 remb_bitrate_ = bitrate;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000263 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000264
Erik Språng242e22b2015-05-11 10:17:43 +0200265 if (remb_enabled_)
266 SetFlag(kRtcpRemb, false);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000267 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
268 // throttled by the caller.
Erik Språng242e22b2015-05-11 10:17:43 +0200269 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000270}
271
Erik Språng61be2a42015-04-27 13:32:52 +0200272bool RTCPSender::TMMBR() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200273 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
274 return IsFlagPresent(RTCPPacketType::kRtcpTmmbr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000275}
276
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000277void RTCPSender::SetTMMBRStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200278 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
279 if (enable) {
280 SetFlag(RTCPPacketType::kRtcpTmmbr, false);
281 } else {
282 ConsumeFlag(RTCPPacketType::kRtcpTmmbr, true);
283 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000284}
285
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000286void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
Erik Språng242e22b2015-05-11 10:17:43 +0200287 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000288 start_timestamp_ = start_timestamp;
289}
290
291void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
292 int64_t capture_time_ms) {
Erik Språng242e22b2015-05-11 10:17:43 +0200293 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000294 last_rtp_timestamp_ = rtp_timestamp;
295 if (capture_time_ms < 0) {
296 // We don't currently get a capture time from VoiceEngine.
Erik Språng242e22b2015-05-11 10:17:43 +0200297 last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000298 } else {
299 last_frame_capture_time_ms_ = capture_time_ms;
300 }
301}
302
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000303void RTCPSender::SetSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200304 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000305
Erik Språng242e22b2015-05-11 10:17:43 +0200306 if (ssrc_ != 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200307 // not first SetSSRC, probably due to a collision
308 // schedule a new RTCP report
309 // make sure that we send a RTP packet
Erik Språng242e22b2015-05-11 10:17:43 +0200310 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
Erik Språng61be2a42015-04-27 13:32:52 +0200311 }
Erik Språng242e22b2015-05-11 10:17:43 +0200312 ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000313}
314
Erik Språng61be2a42015-04-27 13:32:52 +0200315void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200316 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
317 remote_ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000318}
319
Peter Boström9ba52f82015-06-01 14:12:28 +0200320int32_t RTCPSender::SetCNAME(const char* c_name) {
321 if (!c_name)
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000322 return -1;
323
henrikg91d6ede2015-09-17 00:24:34 -0700324 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
Erik Språng242e22b2015-05-11 10:17:43 +0200325 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200326 cname_ = c_name;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000327 return 0;
328}
329
Erik Språng0ea42d32015-06-25 14:46:16 +0200330int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC, const char* c_name) {
331 assert(c_name);
henrikg91d6ede2015-09-17 00:24:34 -0700332 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
Erik Språng242e22b2015-05-11 10:17:43 +0200333 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200334 if (csrc_cnames_.size() >= kRtpCsrcSize)
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000335 return -1;
Erik Språng0ea42d32015-06-25 14:46:16 +0200336
337 csrc_cnames_[SSRC] = c_name;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000338 return 0;
339}
340
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000341int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
Erik Språng242e22b2015-05-11 10:17:43 +0200342 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200343 auto it = csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000344
Erik Språng242e22b2015-05-11 10:17:43 +0200345 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000346 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200347
Erik Språng242e22b2015-05-11 10:17:43 +0200348 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000349 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000350}
351
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000352bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
danilchap162abd32015-12-10 02:39:40 -0800353 /*
354 For audio we use a fix 5 sec interval
niklase@google.com470e71d2011-07-07 08:21:25 +0000355
danilchap162abd32015-12-10 02:39:40 -0800356 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
357 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
358 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000359
360
danilchap162abd32015-12-10 02:39:40 -0800361 From RFC 3550
niklase@google.com470e71d2011-07-07 08:21:25 +0000362
danilchap162abd32015-12-10 02:39:40 -0800363 MAX RTCP BW is 5% if the session BW
364 A send report is approximately 65 bytes inc CNAME
365 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000366
danilchap162abd32015-12-10 02:39:40 -0800367 The RECOMMENDED value for the reduced minimum in seconds is 360
368 divided by the session bandwidth in kilobits/second. This minimum
369 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
niklase@google.com470e71d2011-07-07 08:21:25 +0000370
danilchap162abd32015-12-10 02:39:40 -0800371 If the participant has not yet sent an RTCP packet (the variable
372 initial is true), the constant Tmin is set to 2.5 seconds, else it
373 is set to 5 seconds.
niklase@google.com470e71d2011-07-07 08:21:25 +0000374
danilchap162abd32015-12-10 02:39:40 -0800375 The interval between RTCP packets is varied randomly over the
376 range [0.5,1.5] times the calculated interval to avoid unintended
377 synchronization of all participants
niklase@google.com470e71d2011-07-07 08:21:25 +0000378
danilchap162abd32015-12-10 02:39:40 -0800379 if we send
380 If the participant is a sender (we_sent true), the constant C is
381 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
382 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
383 number of senders.
niklase@google.com470e71d2011-07-07 08:21:25 +0000384
danilchap162abd32015-12-10 02:39:40 -0800385 if we receive only
386 If we_sent is not true, the constant C is set
387 to the average RTCP packet size divided by 75% of the RTCP
388 bandwidth. The constant n is set to the number of receivers
389 (members - senders). If the number of senders is greater than
390 25%, senders and receivers are treated together.
niklase@google.com470e71d2011-07-07 08:21:25 +0000391
danilchap162abd32015-12-10 02:39:40 -0800392 reconsideration NOT required for peer-to-peer
393 "timer reconsideration" is
394 employed. This algorithm implements a simple back-off mechanism
395 which causes users to hold back RTCP packet transmission if the
396 group sizes are increasing.
niklase@google.com470e71d2011-07-07 08:21:25 +0000397
danilchap162abd32015-12-10 02:39:40 -0800398 n = number of members
399 C = avg_size/(rtcpBW/4)
niklase@google.com470e71d2011-07-07 08:21:25 +0000400
danilchap162abd32015-12-10 02:39:40 -0800401 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
niklase@google.com470e71d2011-07-07 08:21:25 +0000402
danilchap162abd32015-12-10 02:39:40 -0800403 4. The calculated interval T is set to a number uniformly distributed
404 between 0.5 and 1.5 times the deterministic calculated interval.
niklase@google.com470e71d2011-07-07 08:21:25 +0000405
danilchap162abd32015-12-10 02:39:40 -0800406 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
407 for the fact that the timer reconsideration algorithm converges to
408 a value of the RTCP bandwidth below the intended average
409 */
niklase@google.com470e71d2011-07-07 08:21:25 +0000410
Erik Språng242e22b2015-05-11 10:17:43 +0200411 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000412
Erik Språng242e22b2015-05-11 10:17:43 +0200413 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
xians@webrtc.org8738d272011-11-25 13:43:53 +0000414
pbosda903ea2015-10-02 02:36:56 -0700415 if (method_ == RtcpMode::kOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000416 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000417
Erik Språng242e22b2015-05-11 10:17:43 +0200418 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200419 // for video key-frames we want to send the RTCP before the large key-frame
420 // if we have a 100 ms margin
421 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
422 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000423
Erik Språng242e22b2015-05-11 10:17:43 +0200424 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200425 return true;
426 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200427 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200428 // wrap
429 return true;
430 }
431 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000432}
433
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000434int64_t RTCPSender::SendTimeOfSendReport(uint32_t sendReport) {
Erik Språng242e22b2015-05-11 10:17:43 +0200435 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000436
Erik Språng61be2a42015-04-27 13:32:52 +0200437 // This is only saved when we are the sender
Erik Språng242e22b2015-05-11 10:17:43 +0200438 if ((last_send_report_[0] == 0) || (sendReport == 0)) {
Erik Språng61be2a42015-04-27 13:32:52 +0200439 return 0; // will be ignored
440 } else {
441 for (int i = 0; i < RTCP_NUMBER_OF_SR; ++i) {
Erik Språng242e22b2015-05-11 10:17:43 +0200442 if (last_send_report_[i] == sendReport)
443 return last_rtcp_time_[i];
niklase@google.com470e71d2011-07-07 08:21:25 +0000444 }
Erik Språng61be2a42015-04-27 13:32:52 +0200445 }
446 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000447}
448
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000449bool RTCPSender::SendTimeOfXrRrReport(uint32_t mid_ntp,
450 int64_t* time_ms) const {
Erik Språng242e22b2015-05-11 10:17:43 +0200451 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000452
453 if (last_xr_rr_.empty()) {
454 return false;
455 }
456 std::map<uint32_t, int64_t>::const_iterator it = last_xr_rr_.find(mid_ntp);
457 if (it == last_xr_rr_.end()) {
458 return false;
459 }
460 *time_ms = it->second;
461 return true;
462}
463
Erik Språngf7c57762015-12-04 10:40:35 +0100464rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildSR(const RtcpContext& ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200465 for (int i = (RTCP_NUMBER_OF_SR - 2); i >= 0; i--) {
466 // shift old
Erik Språng242e22b2015-05-11 10:17:43 +0200467 last_send_report_[i + 1] = last_send_report_[i];
468 last_rtcp_time_[i + 1] = last_rtcp_time_[i];
Erik Språng61be2a42015-04-27 13:32:52 +0200469 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000470
Erik Språngf7c57762015-12-04 10:40:35 +0100471 last_rtcp_time_[0] = Clock::NtpToMs(ctx.ntp_sec_, ctx.ntp_frac_);
472 last_send_report_[0] = (ctx.ntp_sec_ << 16) + (ctx.ntp_frac_ >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000473
Erik Språng61be2a42015-04-27 13:32:52 +0200474 // The timestamp of this RTCP packet should be estimated as the timestamp of
475 // the frame being captured at this moment. We are calculating that
476 // timestamp as the last frame's timestamp + the time since the last frame
477 // was captured.
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200478 uint32_t rtp_timestamp =
479 start_timestamp_ + last_rtp_timestamp_ +
480 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) *
Erik Språngf7c57762015-12-04 10:40:35 +0100481 (ctx.feedback_state_.frequency_hz / 1000);
niklase@google.com470e71d2011-07-07 08:21:25 +0000482
Erik Språngf7c57762015-12-04 10:40:35 +0100483 rtcp::SenderReport* report = new rtcp::SenderReport();
484 report->From(ssrc_);
485 report->WithNtpSec(ctx.ntp_sec_);
486 report->WithNtpFrac(ctx.ntp_frac_);
487 report->WithRtpTimestamp(rtp_timestamp);
488 report->WithPacketCount(ctx.feedback_state_.packets_sent);
489 report->WithOctetCount(ctx.feedback_state_.media_bytes_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000490
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200491 for (auto it : report_blocks_)
Erik Språngf7c57762015-12-04 10:40:35 +0100492 report->WithReportBlock(it.second);
niklase@google.com470e71d2011-07-07 08:21:25 +0000493
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200494 report_blocks_.clear();
Erik Språngf7c57762015-12-04 10:40:35 +0100495
496 return rtc::scoped_ptr<rtcp::SenderReport>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000497}
498
Erik Språngf7c57762015-12-04 10:40:35 +0100499rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildSDES(
500 const RtcpContext& ctx) {
Erik Språng0ea42d32015-06-25 14:46:16 +0200501 size_t length_cname = cname_.length();
henrikg91d6ede2015-09-17 00:24:34 -0700502 RTC_CHECK_LT(length_cname, static_cast<size_t>(RTCP_CNAME_SIZE));
niklase@google.com470e71d2011-07-07 08:21:25 +0000503
Erik Språngf7c57762015-12-04 10:40:35 +0100504 rtcp::Sdes* sdes = new rtcp::Sdes();
505 sdes->WithCName(ssrc_, cname_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200506
507 for (const auto it : csrc_cnames_)
Erik Språngf7c57762015-12-04 10:40:35 +0100508 sdes->WithCName(it.first, it.second);
Erik Språng0ea42d32015-06-25 14:46:16 +0200509
Erik Språngf7c57762015-12-04 10:40:35 +0100510 return rtc::scoped_ptr<rtcp::Sdes>(sdes);
niklase@google.com470e71d2011-07-07 08:21:25 +0000511}
512
Erik Språngf7c57762015-12-04 10:40:35 +0100513rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildRR(const RtcpContext& ctx) {
514 rtcp::ReceiverReport* report = new rtcp::ReceiverReport();
515 report->From(ssrc_);
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200516 for (auto it : report_blocks_)
Erik Språngf7c57762015-12-04 10:40:35 +0100517 report->WithReportBlock(it.second);
Erik Språng61be2a42015-04-27 13:32:52 +0200518
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200519 report_blocks_.clear();
Erik Språngf7c57762015-12-04 10:40:35 +0100520 return rtc::scoped_ptr<rtcp::ReceiverReport>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000521}
522
Erik Språngf7c57762015-12-04 10:40:35 +0100523rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildPLI(const RtcpContext& ctx) {
524 rtcp::Pli* pli = new rtcp::Pli();
525 pli->From(ssrc_);
526 pli->To(remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200527
Erik Språng242e22b2015-05-11 10:17:43 +0200528 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
529 "RTCPSender::PLI");
530 ++packet_type_counter_.pli_packets;
531 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
532 ssrc_, packet_type_counter_.pli_packets);
533
Erik Språngf7c57762015-12-04 10:40:35 +0100534 return rtc::scoped_ptr<rtcp::Pli>(pli);
Erik Språng61be2a42015-04-27 13:32:52 +0200535}
536
Erik Språngf7c57762015-12-04 10:40:35 +0100537rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildFIR(const RtcpContext& ctx) {
538 if (!ctx.repeat_)
sprang62dae192015-08-05 02:35:35 -0700539 ++sequence_number_fir_; // Do not increase if repetition.
niklase@google.com470e71d2011-07-07 08:21:25 +0000540
Erik Språngf7c57762015-12-04 10:40:35 +0100541 rtcp::Fir* fir = new rtcp::Fir();
542 fir->From(ssrc_);
543 fir->To(remote_ssrc_);
544 fir->WithCommandSeqNum(sequence_number_fir_);
Erik Språng242e22b2015-05-11 10:17:43 +0200545
546 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
547 "RTCPSender::FIR");
548 ++packet_type_counter_.fir_packets;
549 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
550 ssrc_, packet_type_counter_.fir_packets);
551
Erik Språngf7c57762015-12-04 10:40:35 +0100552 return rtc::scoped_ptr<rtcp::Fir>(fir);
niklase@google.com470e71d2011-07-07 08:21:25 +0000553}
554
555/*
556 0 1 2 3
557 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
558 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
559 | First | Number | PictureID |
560 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
561*/
Erik Språngf7c57762015-12-04 10:40:35 +0100562rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildSLI(const RtcpContext& ctx) {
563 rtcp::Sli* sli = new rtcp::Sli();
564 sli->From(ssrc_);
565 sli->To(remote_ssrc_);
sprang0365a272015-08-11 01:02:37 -0700566 // Crop picture id to 6 least significant bits.
Erik Språngf7c57762015-12-04 10:40:35 +0100567 sli->WithPictureId(ctx.picture_id_ & 0x3F);
sprang0365a272015-08-11 01:02:37 -0700568
Erik Språngf7c57762015-12-04 10:40:35 +0100569 return rtc::scoped_ptr<rtcp::Sli>(sli);
niklase@google.com470e71d2011-07-07 08:21:25 +0000570}
571
572/*
573 0 1 2 3
574 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
575 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
576 | PB |0| Payload Type| Native RPSI bit string |
577 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
578 | defined per codec ... | Padding (0) |
579 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
580*/
581/*
582* Note: not generic made for VP8
583*/
Erik Språngf7c57762015-12-04 10:40:35 +0100584rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildRPSI(
585 const RtcpContext& ctx) {
586 if (ctx.feedback_state_.send_payload_type == 0xFF)
587 return nullptr;
Erik Språng242e22b2015-05-11 10:17:43 +0200588
Erik Språngf7c57762015-12-04 10:40:35 +0100589 rtcp::Rpsi* rpsi = new rtcp::Rpsi();
590 rpsi->From(ssrc_);
591 rpsi->To(remote_ssrc_);
592 rpsi->WithPayloadType(ctx.feedback_state_.send_payload_type);
593 rpsi->WithPictureId(ctx.picture_id_);
sprangcf7f54d2015-08-13 04:37:42 -0700594
Erik Språngf7c57762015-12-04 10:40:35 +0100595 return rtc::scoped_ptr<rtcp::Rpsi>(rpsi);
niklase@google.com470e71d2011-07-07 08:21:25 +0000596}
597
Erik Språngf7c57762015-12-04 10:40:35 +0100598rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildREMB(
599 const RtcpContext& ctx) {
600 rtcp::Remb* remb = new rtcp::Remb();
601 remb->From(ssrc_);
sprangdd4edc52015-08-21 04:21:51 -0700602 for (uint32_t ssrc : remb_ssrcs_)
Erik Språngf7c57762015-12-04 10:40:35 +0100603 remb->AppliesTo(ssrc);
604 remb->WithBitrateBps(remb_bitrate_);
Erik Språng61be2a42015-04-27 13:32:52 +0200605
Erik Språng242e22b2015-05-11 10:17:43 +0200606 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
607 "RTCPSender::REMB");
608
Erik Språngf7c57762015-12-04 10:40:35 +0100609 return rtc::scoped_ptr<rtcp::Remb>(remb);
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000610}
611
Erik Språng61be2a42015-04-27 13:32:52 +0200612void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
Erik Språng242e22b2015-05-11 10:17:43 +0200613 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
614 tmmbr_send_ = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000615}
616
Erik Språngf7c57762015-12-04 10:40:35 +0100617rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBR(
618 const RtcpContext& ctx) {
619 if (ctx.feedback_state_.module == nullptr)
620 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200621 // Before sending the TMMBR check the received TMMBN, only an owner is
622 // allowed to raise the bitrate:
623 // * If the sender is an owner of the TMMBN -> send TMMBR
624 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000625
Erik Språng61be2a42015-04-27 13:32:52 +0200626 // get current bounding set from RTCP receiver
627 bool tmmbrOwner = false;
628 // store in candidateSet, allocates one extra slot
Erik Språng242e22b2015-05-11 10:17:43 +0200629 TMMBRSet* candidateSet = tmmbr_help_.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000630
Erik Språng242e22b2015-05-11 10:17:43 +0200631 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
632 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
Erik Språng61be2a42015-04-27 13:32:52 +0200633 // since RTCPreceiver is not doing the reverse we should be fine
634 int32_t lengthOfBoundingSet =
danilchap6db6cdc2015-12-15 02:54:47 -0800635 ctx.feedback_state_.module->BoundingSet(&tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +0000636
Erik Språng61be2a42015-04-27 13:32:52 +0200637 if (lengthOfBoundingSet > 0) {
638 for (int32_t i = 0; i < lengthOfBoundingSet; i++) {
Erik Språng242e22b2015-05-11 10:17:43 +0200639 if (candidateSet->Tmmbr(i) == tmmbr_send_ &&
640 candidateSet->PacketOH(i) == packet_oh_send_) {
Erik Språngf7c57762015-12-04 10:40:35 +0100641 // Do not send the same tuple.
642 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200643 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000644 }
Erik Språng61be2a42015-04-27 13:32:52 +0200645 if (!tmmbrOwner) {
646 // use received bounding set as candidate set
647 // add current tuple
Erik Språng242e22b2015-05-11 10:17:43 +0200648 candidateSet->SetEntry(lengthOfBoundingSet, tmmbr_send_, packet_oh_send_,
649 ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200650 int numCandidates = lengthOfBoundingSet + 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000651
Erik Språng61be2a42015-04-27 13:32:52 +0200652 // find bounding set
Erik Språngf7c57762015-12-04 10:40:35 +0100653 TMMBRSet* boundingSet = nullptr;
Erik Språng242e22b2015-05-11 10:17:43 +0200654 int numBoundingSet = tmmbr_help_.FindTMMBRBoundingSet(boundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200655 if (numBoundingSet > 0 || numBoundingSet <= numCandidates)
Erik Språng242e22b2015-05-11 10:17:43 +0200656 tmmbrOwner = tmmbr_help_.IsOwner(ssrc_, numBoundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200657 if (!tmmbrOwner) {
Erik Språngf7c57762015-12-04 10:40:35 +0100658 // Did not enter bounding set, no meaning to send this request.
659 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200660 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000661 }
Erik Språng61be2a42015-04-27 13:32:52 +0200662 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000663
Erik Språngf7c57762015-12-04 10:40:35 +0100664 if (!tmmbr_send_)
665 return nullptr;
sprang81a3e602015-08-21 05:30:11 -0700666
Erik Språngf7c57762015-12-04 10:40:35 +0100667 rtcp::Tmmbr* tmmbr = new rtcp::Tmmbr();
668 tmmbr->From(ssrc_);
669 tmmbr->To(remote_ssrc_);
670 tmmbr->WithBitrateKbps(tmmbr_send_);
671 tmmbr->WithOverhead(packet_oh_send_);
672
673 return rtc::scoped_ptr<rtcp::Tmmbr>(tmmbr);
Erik Språng61be2a42015-04-27 13:32:52 +0200674}
675
Erik Språngf7c57762015-12-04 10:40:35 +0100676rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBN(
677 const RtcpContext& ctx) {
Erik Språng242e22b2015-05-11 10:17:43 +0200678 TMMBRSet* boundingSet = tmmbr_help_.BoundingSetToSend();
Erik Språngf7c57762015-12-04 10:40:35 +0100679 if (boundingSet == nullptr)
680 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200681
Erik Språngf7c57762015-12-04 10:40:35 +0100682 rtcp::Tmmbn* tmmbn = new rtcp::Tmmbn();
683 tmmbn->From(ssrc_);
sprangd83df502015-08-27 01:05:08 -0700684 for (uint32_t i = 0; i < boundingSet->lengthOfSet(); i++) {
685 if (boundingSet->Tmmbr(i) > 0) {
Erik Språngf7c57762015-12-04 10:40:35 +0100686 tmmbn->WithTmmbr(boundingSet->Ssrc(i), boundingSet->Tmmbr(i),
687 boundingSet->PacketOH(i));
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000688 }
Erik Språng61be2a42015-04-27 13:32:52 +0200689 }
sprangd83df502015-08-27 01:05:08 -0700690
Erik Språngf7c57762015-12-04 10:40:35 +0100691 return rtc::scoped_ptr<rtcp::Tmmbn>(tmmbn);
niklase@google.com470e71d2011-07-07 08:21:25 +0000692}
693
Erik Språngf7c57762015-12-04 10:40:35 +0100694rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildAPP(const RtcpContext& ctx) {
695 rtcp::App* app = new rtcp::App();
696 app->From(ssrc_);
697 app->WithSubType(app_sub_type_);
698 app->WithName(app_name_);
699 app->WithData(app_data_.get(), app_length_);
Erik Språng521875a2015-09-01 10:11:16 +0200700
Erik Språngf7c57762015-12-04 10:40:35 +0100701 return rtc::scoped_ptr<rtcp::App>(app);
Erik Språng61be2a42015-04-27 13:32:52 +0200702}
703
Erik Språngf7c57762015-12-04 10:40:35 +0100704rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildNACK(
705 const RtcpContext& ctx) {
706 rtcp::Nack* nack = new rtcp::Nack();
707 nack->From(ssrc_);
708 nack->To(remote_ssrc_);
709 nack->WithList(ctx.nack_list_, ctx.nack_size_);
Erik Språng61be2a42015-04-27 13:32:52 +0200710
711 // Report stats.
712 NACKStringBuilder stringBuilder;
Erik Språngf7c57762015-12-04 10:40:35 +0100713 for (int idx = 0; idx < ctx.nack_size_; ++idx) {
714 stringBuilder.PushNACK(ctx.nack_list_[idx]);
715 nack_stats_.ReportRequest(ctx.nack_list_[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +0200716 }
Erik Språng61be2a42015-04-27 13:32:52 +0200717 packet_type_counter_.nack_requests = nack_stats_.requests();
718 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +0200719
720 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
721 "RTCPSender::NACK", "nacks",
722 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
723 ++packet_type_counter_.nack_packets;
724 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
725 ssrc_, packet_type_counter_.nack_packets);
726
Erik Språngf7c57762015-12-04 10:40:35 +0100727 return rtc::scoped_ptr<rtcp::Nack>(nack);
Erik Språng61be2a42015-04-27 13:32:52 +0200728}
729
Erik Språngf7c57762015-12-04 10:40:35 +0100730rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildBYE(const RtcpContext& ctx) {
731 rtcp::Bye* bye = new rtcp::Bye();
732 bye->From(ssrc_);
sprangd8ee4f92015-08-24 03:25:19 -0700733 for (uint32_t csrc : csrcs_)
Erik Språngf7c57762015-12-04 10:40:35 +0100734 bye->WithCsrc(csrc);
sprangd8ee4f92015-08-24 03:25:19 -0700735
Erik Språngf7c57762015-12-04 10:40:35 +0100736 return rtc::scoped_ptr<rtcp::Bye>(bye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000737}
738
Erik Språngf7c57762015-12-04 10:40:35 +0100739rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildReceiverReferenceTime(
740 const RtcpContext& ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200741 if (last_xr_rr_.size() >= RTCP_NUMBER_OF_SR)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000742 last_xr_rr_.erase(last_xr_rr_.begin());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000743 last_xr_rr_.insert(std::pair<uint32_t, int64_t>(
Erik Språngf7c57762015-12-04 10:40:35 +0100744 RTCPUtility::MidNtp(ctx.ntp_sec_, ctx.ntp_frac_),
745 Clock::NtpToMs(ctx.ntp_sec_, ctx.ntp_frac_)));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000746
Danil Chapovalov256e5b22016-01-15 14:16:24 +0100747 rtcp::ExtendedReports* xr = new rtcp::ExtendedReports();
Erik Språngf7c57762015-12-04 10:40:35 +0100748 xr->From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000749
Erik Språngca28fdc2015-08-31 14:00:50 +0200750 rtcp::Rrtr rrtr;
Danil Chapovalovfc47ed62015-12-07 14:46:35 +0100751 rrtr.WithNtp(NtpTime(ctx.ntp_sec_, ctx.ntp_frac_));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000752
Erik Språngf7c57762015-12-04 10:40:35 +0100753 xr->WithRrtr(&rrtr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000754
Erik Språngca28fdc2015-08-31 14:00:50 +0200755 // TODO(sprang): Merge XR report sending to contain all of RRTR, DLRR, VOIP?
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000756
Danil Chapovalov256e5b22016-01-15 14:16:24 +0100757 return rtc::scoped_ptr<rtcp::RtcpPacket>(xr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000758}
759
Erik Språngf7c57762015-12-04 10:40:35 +0100760rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildDlrr(
761 const RtcpContext& ctx) {
Danil Chapovalov256e5b22016-01-15 14:16:24 +0100762 rtcp::ExtendedReports* xr = new rtcp::ExtendedReports();
Erik Språngf7c57762015-12-04 10:40:35 +0100763 xr->From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000764
Erik Språngca28fdc2015-08-31 14:00:50 +0200765 rtcp::Dlrr dlrr;
Erik Språngf7c57762015-12-04 10:40:35 +0100766 const RtcpReceiveTimeInfo& info = ctx.feedback_state_.last_xr_rr;
Erik Språngca28fdc2015-08-31 14:00:50 +0200767 dlrr.WithDlrrItem(info.sourceSSRC, info.lastRR, info.delaySinceLastRR);
768
Erik Språngf7c57762015-12-04 10:40:35 +0100769 xr->WithDlrr(&dlrr);
Erik Språngca28fdc2015-08-31 14:00:50 +0200770
Danil Chapovalov256e5b22016-01-15 14:16:24 +0100771 return rtc::scoped_ptr<rtcp::RtcpPacket>(xr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000772}
773
Erik Språng242e22b2015-05-11 10:17:43 +0200774// TODO(sprang): Add a unit test for this, or remove if the code isn't used.
Erik Språngf7c57762015-12-04 10:40:35 +0100775rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildVoIPMetric(
776 const RtcpContext& context) {
Danil Chapovalov256e5b22016-01-15 14:16:24 +0100777 rtcp::ExtendedReports* xr = new rtcp::ExtendedReports();
Erik Språngf7c57762015-12-04 10:40:35 +0100778 xr->From(ssrc_);
Erik Språngca28fdc2015-08-31 14:00:50 +0200779
780 rtcp::VoipMetric voip;
781 voip.To(remote_ssrc_);
danilchap91941ae2015-12-15 07:06:36 -0800782 voip.WithVoipMetric(xr_voip_metric_);
Erik Språngca28fdc2015-08-31 14:00:50 +0200783
Erik Språngf7c57762015-12-04 10:40:35 +0100784 xr->WithVoipMetric(&voip);
Erik Språngca28fdc2015-08-31 14:00:50 +0200785
Danil Chapovalov256e5b22016-01-15 14:16:24 +0100786 return rtc::scoped_ptr<rtcp::RtcpPacket>(xr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000787}
788
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000789int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200790 RTCPPacketType packetType,
791 int32_t nack_size,
792 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000793 bool repeat,
794 uint64_t pictureID) {
Erik Språng242e22b2015-05-11 10:17:43 +0200795 return SendCompoundRTCP(
796 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
797 nack_size, nack_list, repeat, pictureID);
798}
799
800int32_t RTCPSender::SendCompoundRTCP(
801 const FeedbackState& feedback_state,
Erik Språngf7c57762015-12-04 10:40:35 +0100802 const std::set<RTCPPacketType>& packet_types,
Erik Språng242e22b2015-05-11 10:17:43 +0200803 int32_t nack_size,
804 const uint16_t* nack_list,
805 bool repeat,
806 uint64_t pictureID) {
Erik Språngf7c57762015-12-04 10:40:35 +0100807 PacketContainer container(transport_);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000808 {
Erik Språng242e22b2015-05-11 10:17:43 +0200809 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
pbosda903ea2015-10-02 02:36:56 -0700810 if (method_ == RtcpMode::kOff) {
Erik Språng61be2a42015-04-27 13:32:52 +0200811 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
812 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +0000813 }
Erik Språngf7c57762015-12-04 10:40:35 +0100814
815 // We need to send our NTP even if we haven't received any reports.
816 uint32_t ntp_sec;
817 uint32_t ntp_frac;
818 clock_->CurrentNtp(ntp_sec, ntp_frac);
819 RtcpContext context(feedback_state, nack_size, nack_list, repeat, pictureID,
820 ntp_sec, ntp_frac, &container);
821
822 PrepareReport(packet_types, feedback_state);
823
824 auto it = report_flags_.begin();
825 while (it != report_flags_.end()) {
826 auto builder_it = builders_.find(it->type);
827 RTC_DCHECK(builder_it != builders_.end());
828 if (it->is_volatile) {
829 report_flags_.erase(it++);
830 } else {
831 ++it;
832 }
833
834 BuilderFunc func = builder_it->second;
835 rtc::scoped_ptr<rtcp::RtcpPacket> packet = (this->*func)(context);
836 if (packet.get() == nullptr)
837 return -1;
838 container.Append(packet.release());
839 }
840
841 if (packet_type_counter_observer_ != nullptr) {
842 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
843 remote_ssrc_, packet_type_counter_);
844 }
845
846 RTC_DCHECK(AllVolatileFlagsConsumed());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000847 }
Erik Språng61be2a42015-04-27 13:32:52 +0200848
Erik Språngf7c57762015-12-04 10:40:35 +0100849 size_t bytes_sent = container.SendPackets();
850 return bytes_sent == 0 ? -1 : 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000851}
852
Erik Språngf7c57762015-12-04 10:40:35 +0100853void RTCPSender::PrepareReport(const std::set<RTCPPacketType>& packetTypes,
854 const FeedbackState& feedback_state) {
Erik Språng242e22b2015-05-11 10:17:43 +0200855 // Add all flags as volatile. Non volatile entries will not be overwritten
856 // and all new volatile flags added will be consumed by the end of this call.
857 SetFlags(packetTypes, true);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000858
Erik Språng61be2a42015-04-27 13:32:52 +0200859 if (packet_type_counter_.first_packet_time_ms == -1)
Erik Språng242e22b2015-05-11 10:17:43 +0200860 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språng61be2a42015-04-27 13:32:52 +0200861
Erik Språng242e22b2015-05-11 10:17:43 +0200862 bool generate_report;
863 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
864 // Report type already explicitly set, don't automatically populate.
865 generate_report = true;
henrikg91d6ede2015-09-17 00:24:34 -0700866 RTC_DCHECK(ConsumeFlag(kRtcpReport) == false);
Erik Språng242e22b2015-05-11 10:17:43 +0200867 } else {
868 generate_report =
pbosda903ea2015-10-02 02:36:56 -0700869 (ConsumeFlag(kRtcpReport) && method_ == RtcpMode::kReducedSize) ||
870 method_ == RtcpMode::kCompound;
Erik Språng242e22b2015-05-11 10:17:43 +0200871 if (generate_report)
872 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000873 }
874
Erik Språng0ea42d32015-06-25 14:46:16 +0200875 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
Erik Språng242e22b2015-05-11 10:17:43 +0200876 SetFlag(kRtcpSdes, true);
877
Erik Språng242e22b2015-05-11 10:17:43 +0200878 if (generate_report) {
879 if (!sending_ && xr_send_receiver_reference_time_enabled_)
880 SetFlag(kRtcpXrReceiverReferenceTime, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200881 if (feedback_state.has_last_xr_rr)
Erik Språng242e22b2015-05-11 10:17:43 +0200882 SetFlag(kRtcpXrDlrrReportBlock, true);
883
884 // generate next time to send an RTCP report
danilchap47a740b2015-12-15 00:30:07 -0800885 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000886
danilchap47a740b2015-12-15 00:30:07 -0800887 if (!audio_) {
Erik Språng242e22b2015-05-11 10:17:43 +0200888 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200889 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
890 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
891 if (send_bitrate_kbit != 0)
892 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000893 }
Erik Språng61be2a42015-04-27 13:32:52 +0200894 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
895 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
Erik Språng61be2a42015-04-27 13:32:52 +0200896 }
danilchap47a740b2015-12-15 00:30:07 -0800897 // The interval between RTCP packets is varied randomly over the
898 // range [1/2,3/2] times the calculated interval.
899 uint32_t timeToNext =
900 random_.Rand(minIntervalMs * 1 / 2, minIntervalMs * 3 / 2);
Erik Språng242e22b2015-05-11 10:17:43 +0200901 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000902
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000903 StatisticianMap statisticians =
904 receive_statistics_->GetActiveStatisticians();
danilchapa72e7342015-12-22 08:07:45 -0800905 RTC_DCHECK(report_blocks_.empty());
906 for (auto& it : statisticians) {
907 AddReportBlock(feedback_state, it.first, it.second);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000908 }
909 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000910}
911
danilchapa72e7342015-12-22 08:07:45 -0800912bool RTCPSender::AddReportBlock(const FeedbackState& feedback_state,
913 uint32_t ssrc,
914 StreamStatistician* statistician) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000915 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000916 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000917 if (!statistician->GetStatistics(&stats, true))
918 return false;
danilchapa72e7342015-12-22 08:07:45 -0800919
920 if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) {
921 LOG(LS_WARNING) << "Too many report blocks.";
922 return false;
923 }
924 RTC_DCHECK(report_blocks_.find(ssrc) == report_blocks_.end());
925 rtcp::ReportBlock* block = &report_blocks_[ssrc];
926 block->To(ssrc);
927 block->WithFractionLost(stats.fraction_lost);
928 if (!block->WithCumulativeLost(stats.cumulative_lost)) {
929 report_blocks_.erase(ssrc);
930 LOG(LS_WARNING) << "Cumulative lost is oversized.";
931 return false;
932 }
933 block->WithExtHighestSeqNum(stats.extended_max_sequence_number);
934 block->WithJitter(stats.jitter);
935 block->WithLastSr(feedback_state.remote_sr);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000936
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200937 // TODO(sprang): Do we really need separate time stamps for each report?
938 // Get our NTP as late as possible to avoid a race.
939 uint32_t ntp_secs;
940 uint32_t ntp_frac;
941 clock_->CurrentNtp(ntp_secs, ntp_frac);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000942
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200943 // Delay since last received report.
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000944 if ((feedback_state.last_rr_ntp_secs != 0) ||
945 (feedback_state.last_rr_ntp_frac != 0)) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200946 // Get the 16 lowest bits of seconds and the 16 highest bits of fractions.
947 uint32_t now = ntp_secs & 0x0000FFFF;
Erik Språng61be2a42015-04-27 13:32:52 +0200948 now <<= 16;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200949 now += (ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000950
Erik Språng61be2a42015-04-27 13:32:52 +0200951 uint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
952 receiveTime <<= 16;
953 receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000954
danilchapa72e7342015-12-22 08:07:45 -0800955 block->WithDelayLastSr(now - receiveTime);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000956 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000957 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000958}
959
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000960void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
961 assert(csrcs.size() <= kRtpCsrcSize);
Erik Språng242e22b2015-05-11 10:17:43 +0200962 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000963 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +0000964}
965
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000966int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
967 uint32_t name,
968 const uint8_t* data,
969 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +0200970 if (length % 4 != 0) {
971 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
972 return -1;
973 }
Erik Språng242e22b2015-05-11 10:17:43 +0200974 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000975
Erik Språng242e22b2015-05-11 10:17:43 +0200976 SetFlag(kRtcpApp, true);
977 app_sub_type_ = subType;
978 app_name_ = name;
979 app_data_.reset(new uint8_t[length]);
980 app_length_ = length;
981 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +0200982 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000983}
984
Erik Språng61be2a42015-04-27 13:32:52 +0200985int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
Erik Språng242e22b2015-05-11 10:17:43 +0200986 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
987 memcpy(&xr_voip_metric_, VoIPMetric, sizeof(RTCPVoIPMetric));
niklase@google.com470e71d2011-07-07 08:21:25 +0000988
Erik Språng242e22b2015-05-11 10:17:43 +0200989 SetFlag(kRtcpXrVoipMetric, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200990 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000991}
992
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000993void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200994 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
995 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000996}
997
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000998bool RTCPSender::RtcpXrReceiverReferenceTime() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200999 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1000 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00001001}
1002
niklase@google.com470e71d2011-07-07 08:21:25 +00001003// no callbacks allowed inside this function
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001004int32_t RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
1005 uint32_t maxBitrateKbit) {
Erik Språng242e22b2015-05-11 10:17:43 +02001006 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +00001007
Erik Språng242e22b2015-05-11 10:17:43 +02001008 if (0 == tmmbr_help_.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit)) {
1009 SetFlag(kRtcpTmmbn, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001010 return 0;
1011 }
1012 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001013}
Erik Språng61be2a42015-04-27 13:32:52 +02001014
Erik Språng242e22b2015-05-11 10:17:43 +02001015void RTCPSender::SetFlag(RTCPPacketType type, bool is_volatile) {
1016 report_flags_.insert(ReportFlag(type, is_volatile));
1017}
1018
1019void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
1020 bool is_volatile) {
1021 for (RTCPPacketType type : types)
1022 SetFlag(type, is_volatile);
1023}
1024
1025bool RTCPSender::IsFlagPresent(RTCPPacketType type) const {
1026 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
1027}
1028
1029bool RTCPSender::ConsumeFlag(RTCPPacketType type, bool forced) {
1030 auto it = report_flags_.find(ReportFlag(type, false));
1031 if (it == report_flags_.end())
1032 return false;
1033 if (it->is_volatile || forced)
1034 report_flags_.erase((it));
1035 return true;
1036}
1037
1038bool RTCPSender::AllVolatileFlagsConsumed() const {
1039 for (const ReportFlag& flag : report_flags_) {
1040 if (flag.is_volatile)
1041 return false;
1042 }
1043 return true;
1044}
1045
sprang233bd872015-09-08 13:25:16 -07001046bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
sprang233bd872015-09-08 13:25:16 -07001047 class Sender : public rtcp::RtcpPacket::PacketReadyCallback {
1048 public:
danilchap6db6cdc2015-12-15 02:54:47 -08001049 explicit Sender(Transport* transport)
Peter Boströmac547a62015-09-17 23:03:57 +02001050 : transport_(transport), send_failure_(false) {}
sprang233bd872015-09-08 13:25:16 -07001051
1052 void OnPacketReady(uint8_t* data, size_t length) override {
pbos2d566682015-09-28 09:59:31 -07001053 if (!transport_->SendRtcp(data, length))
sprang233bd872015-09-08 13:25:16 -07001054 send_failure_ = true;
1055 }
1056
1057 Transport* const transport_;
sprang233bd872015-09-08 13:25:16 -07001058 bool send_failure_;
sprang86fd9ed2015-09-29 04:45:43 -07001059 } sender(transport_);
sprang233bd872015-09-08 13:25:16 -07001060
1061 uint8_t buffer[IP_PACKET_SIZE];
1062 return packet.BuildExternalBuffer(buffer, IP_PACKET_SIZE, &sender) &&
1063 !sender.send_failure_;
1064}
1065
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001066} // namespace webrtc