blob: 7b47ab7c6811ada5dea6b3be73b68327db5e3241 [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"
danilchapa8890a52015-12-22 03:43:04 -080027#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/nack.h"
danilchapf8385ad2015-11-27 05:36:09 -080028#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/pli.h"
Danil Chapovalov97f7e132015-12-04 16:13:30 +010029#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
danilchap92e677a2016-01-12 10:04:52 -080030#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sli.h"
danilchapef3d8052016-01-11 03:31:08 -080031#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbn.h"
danilchap7e8145f2016-01-11 11:49:19 -080032#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbr.h"
sprang233bd872015-09-08 13:25:16 -070033#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
tommie4f96502015-10-20 23:00:48 -070034#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010035#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000036
niklase@google.com470e71d2011-07-07 08:21:25 +000037namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000038
39using RTCPUtility::RTCPCnameInformation;
40
Erik Språng61be2a42015-04-27 13:32:52 +020041NACKStringBuilder::NACKStringBuilder()
danilchap162abd32015-12-10 02:39:40 -080042 : stream_(""), count_(0), prevNack_(0), consecutive_(false) {}
edjee@google.com79b02892013-04-04 19:43:34 +000043
pbos@webrtc.orgf3e4cee2013-07-31 15:17:19 +000044NACKStringBuilder::~NACKStringBuilder() {}
45
danilchap162abd32015-12-10 02:39:40 -080046void NACKStringBuilder::PushNACK(uint16_t nack) {
Erik Språng242e22b2015-05-11 10:17:43 +020047 if (count_ == 0) {
48 stream_ << nack;
49 } else if (nack == prevNack_ + 1) {
50 consecutive_ = true;
Erik Språng61be2a42015-04-27 13:32:52 +020051 } else {
Erik Språng242e22b2015-05-11 10:17:43 +020052 if (consecutive_) {
53 stream_ << "-" << prevNack_;
54 consecutive_ = false;
edjee@google.com79b02892013-04-04 19:43:34 +000055 }
Erik Språng242e22b2015-05-11 10:17:43 +020056 stream_ << "," << nack;
Erik Språng61be2a42015-04-27 13:32:52 +020057 }
Erik Språng242e22b2015-05-11 10:17:43 +020058 count_++;
59 prevNack_ = nack;
edjee@google.com79b02892013-04-04 19:43:34 +000060}
61
Erik Språng61be2a42015-04-27 13:32:52 +020062std::string NACKStringBuilder::GetResult() {
Erik Språng242e22b2015-05-11 10:17:43 +020063 if (consecutive_) {
64 stream_ << "-" << prevNack_;
65 consecutive_ = false;
Erik Språng61be2a42015-04-27 13:32:52 +020066 }
Erik Språng242e22b2015-05-11 10:17:43 +020067 return stream_.str();
edjee@google.com79b02892013-04-04 19:43:34 +000068}
69
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000070RTCPSender::FeedbackState::FeedbackState()
71 : send_payload_type(0),
72 frequency_hz(0),
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +000073 packets_sent(0),
74 media_bytes_sent(0),
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000075 send_bitrate(0),
76 last_rr_ntp_secs(0),
77 last_rr_ntp_frac(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000078 remote_sr(0),
Erik Språng61be2a42015-04-27 13:32:52 +020079 has_last_xr_rr(false),
danilchap162abd32015-12-10 02:39:40 -080080 module(nullptr) {}
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000081
Erik Språngf7c57762015-12-04 10:40:35 +010082class PacketContainer : public rtcp::Empty,
83 public rtcp::RtcpPacket::PacketReadyCallback {
84 public:
85 explicit PacketContainer(Transport* transport)
86 : transport_(transport), bytes_sent_(0) {}
87 virtual ~PacketContainer() {
88 for (RtcpPacket* packet : appended_packets_)
89 delete packet;
90 }
91
92 void OnPacketReady(uint8_t* data, size_t length) override {
93 if (transport_->SendRtcp(data, length))
94 bytes_sent_ += length;
95 }
96
97 size_t SendPackets() {
98 rtcp::Empty::Build(this);
99 return bytes_sent_;
100 }
101
102 private:
103 Transport* transport_;
104 size_t bytes_sent_;
105};
106
107class RTCPSender::RtcpContext {
108 public:
Erik Språng242e22b2015-05-11 10:17:43 +0200109 RtcpContext(const FeedbackState& feedback_state,
110 int32_t nack_size,
111 const uint16_t* nack_list,
112 bool repeat,
113 uint64_t picture_id,
Erik Språngf7c57762015-12-04 10:40:35 +0100114 uint32_t ntp_sec,
115 uint32_t ntp_frac,
116 PacketContainer* container)
117 : feedback_state_(feedback_state),
118 nack_size_(nack_size),
119 nack_list_(nack_list),
120 repeat_(repeat),
121 picture_id_(picture_id),
122 ntp_sec_(ntp_sec),
123 ntp_frac_(ntp_frac),
124 container_(container) {}
Erik Språng242e22b2015-05-11 10:17:43 +0200125
Erik Språngf7c57762015-12-04 10:40:35 +0100126 virtual ~RtcpContext() {}
Erik Språng242e22b2015-05-11 10:17:43 +0200127
Erik Språngf7c57762015-12-04 10:40:35 +0100128 const FeedbackState& feedback_state_;
129 const int32_t nack_size_;
130 const uint16_t* nack_list_;
131 const bool repeat_;
132 const uint64_t picture_id_;
133 const uint32_t ntp_sec_;
134 const uint32_t ntp_frac_;
Erik Språng242e22b2015-05-11 10:17:43 +0200135
Erik Språngf7c57762015-12-04 10:40:35 +0100136 PacketContainer* const container_;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200137};
138
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000139RTCPSender::RTCPSender(
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000140 bool audio,
141 Clock* clock,
142 ReceiveStatistics* receive_statistics,
sprang86fd9ed2015-09-29 04:45:43 -0700143 RtcpPacketTypeCounterObserver* packet_type_counter_observer,
144 Transport* outgoing_transport)
Peter Boströmac547a62015-09-17 23:03:57 +0200145 : audio_(audio),
Erik Språng242e22b2015-05-11 10:17:43 +0200146 clock_(clock),
danilchap47a740b2015-12-15 00:30:07 -0800147 random_(clock_->TimeInMicroseconds()),
pbosda903ea2015-10-02 02:36:56 -0700148 method_(RtcpMode::kOff),
sprang86fd9ed2015-09-29 04:45:43 -0700149 transport_(outgoing_transport),
niklase@google.com470e71d2011-07-07 08:21:25 +0000150
Erik Språng242e22b2015-05-11 10:17:43 +0200151 critical_section_rtcp_sender_(
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000152 CriticalSectionWrapper::CreateCriticalSection()),
Erik Språng242e22b2015-05-11 10:17:43 +0200153 using_nack_(false),
154 sending_(false),
155 remb_enabled_(false),
Erik Språng242e22b2015-05-11 10:17:43 +0200156 next_time_to_send_rtcp_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000157 start_timestamp_(0),
158 last_rtp_timestamp_(0),
159 last_frame_capture_time_ms_(-1),
Erik Språng242e22b2015-05-11 10:17:43 +0200160 ssrc_(0),
161 remote_ssrc_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000162 receive_statistics_(receive_statistics),
niklase@google.com470e71d2011-07-07 08:21:25 +0000163
Erik Språng242e22b2015-05-11 10:17:43 +0200164 sequence_number_fir_(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000165
Erik Språng242e22b2015-05-11 10:17:43 +0200166 remb_bitrate_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000167
Erik Språng242e22b2015-05-11 10:17:43 +0200168 tmmbr_help_(),
169 tmmbr_send_(0),
170 packet_oh_send_(0),
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000171
Erik Språng242e22b2015-05-11 10:17:43 +0200172 app_sub_type_(0),
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200173 app_name_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200174 app_data_(nullptr),
175 app_length_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000176
Erik Språng242e22b2015-05-11 10:17:43 +0200177 xr_send_receiver_reference_time_enabled_(false),
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000178 packet_type_counter_observer_(packet_type_counter_observer) {
Erik Språng242e22b2015-05-11 10:17:43 +0200179 memset(last_send_report_, 0, sizeof(last_send_report_));
180 memset(last_rtcp_time_, 0, sizeof(last_rtcp_time_));
sprang86fd9ed2015-09-29 04:45:43 -0700181 RTC_DCHECK(transport_ != nullptr);
Erik Språng242e22b2015-05-11 10:17:43 +0200182
183 builders_[kRtcpSr] = &RTCPSender::BuildSR;
184 builders_[kRtcpRr] = &RTCPSender::BuildRR;
Erik Språng0ea42d32015-06-25 14:46:16 +0200185 builders_[kRtcpSdes] = &RTCPSender::BuildSDES;
Erik Språng242e22b2015-05-11 10:17:43 +0200186 builders_[kRtcpPli] = &RTCPSender::BuildPLI;
187 builders_[kRtcpFir] = &RTCPSender::BuildFIR;
188 builders_[kRtcpSli] = &RTCPSender::BuildSLI;
189 builders_[kRtcpRpsi] = &RTCPSender::BuildRPSI;
190 builders_[kRtcpRemb] = &RTCPSender::BuildREMB;
191 builders_[kRtcpBye] = &RTCPSender::BuildBYE;
192 builders_[kRtcpApp] = &RTCPSender::BuildAPP;
193 builders_[kRtcpTmmbr] = &RTCPSender::BuildTMMBR;
194 builders_[kRtcpTmmbn] = &RTCPSender::BuildTMMBN;
195 builders_[kRtcpNack] = &RTCPSender::BuildNACK;
196 builders_[kRtcpXrVoipMetric] = &RTCPSender::BuildVoIPMetric;
197 builders_[kRtcpXrReceiverReferenceTime] =
198 &RTCPSender::BuildReceiverReferenceTime;
199 builders_[kRtcpXrDlrrReportBlock] = &RTCPSender::BuildDlrr;
niklase@google.com470e71d2011-07-07 08:21:25 +0000200}
201
danilchap162abd32015-12-10 02:39:40 -0800202RTCPSender::~RTCPSender() {}
niklase@google.com470e71d2011-07-07 08:21:25 +0000203
pbosda903ea2015-10-02 02:36:56 -0700204RtcpMode RTCPSender::Status() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200205 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
206 return method_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000207}
208
pbosda903ea2015-10-02 02:36:56 -0700209void RTCPSender::SetRTCPStatus(RtcpMode method) {
Erik Språng242e22b2015-05-11 10:17:43 +0200210 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
211 method_ = method;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000212
pbosda903ea2015-10-02 02:36:56 -0700213 if (method == RtcpMode::kOff)
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000214 return;
Erik Språng242e22b2015-05-11 10:17:43 +0200215 next_time_to_send_rtcp_ =
216 clock_->TimeInMilliseconds() +
217 (audio_ ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000218}
219
Erik Språng61be2a42015-04-27 13:32:52 +0200220bool RTCPSender::Sending() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200221 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
222 return sending_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000223}
224
Erik Språng61be2a42015-04-27 13:32:52 +0200225int32_t RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
226 bool sending) {
227 bool sendRTCPBye = false;
228 {
Erik Språng242e22b2015-05-11 10:17:43 +0200229 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000230
pbosda903ea2015-10-02 02:36:56 -0700231 if (method_ != RtcpMode::kOff) {
Erik Språng242e22b2015-05-11 10:17:43 +0200232 if (sending == false && sending_ == true) {
Erik Språng61be2a42015-04-27 13:32:52 +0200233 // Trigger RTCP bye
234 sendRTCPBye = true;
235 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000236 }
Erik Språng242e22b2015-05-11 10:17:43 +0200237 sending_ = sending;
Erik Språng61be2a42015-04-27 13:32:52 +0200238 }
239 if (sendRTCPBye)
240 return SendRTCP(feedback_state, kRtcpBye);
241 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000242}
243
Erik Språng61be2a42015-04-27 13:32:52 +0200244bool RTCPSender::REMB() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200245 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
246 return remb_enabled_;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000247}
248
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000249void RTCPSender::SetREMBStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200250 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
251 remb_enabled_ = enable;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000252}
253
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000254void RTCPSender::SetREMBData(uint32_t bitrate,
255 const std::vector<uint32_t>& ssrcs) {
Erik Språng242e22b2015-05-11 10:17:43 +0200256 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
257 remb_bitrate_ = bitrate;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000258 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000259
Erik Språng242e22b2015-05-11 10:17:43 +0200260 if (remb_enabled_)
261 SetFlag(kRtcpRemb, false);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000262 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
263 // throttled by the caller.
Erik Språng242e22b2015-05-11 10:17:43 +0200264 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000265}
266
Erik Språng61be2a42015-04-27 13:32:52 +0200267bool RTCPSender::TMMBR() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200268 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
269 return IsFlagPresent(RTCPPacketType::kRtcpTmmbr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000270}
271
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000272void RTCPSender::SetTMMBRStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200273 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
274 if (enable) {
275 SetFlag(RTCPPacketType::kRtcpTmmbr, false);
276 } else {
277 ConsumeFlag(RTCPPacketType::kRtcpTmmbr, true);
278 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000279}
280
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000281void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
Erik Språng242e22b2015-05-11 10:17:43 +0200282 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000283 start_timestamp_ = start_timestamp;
284}
285
286void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
287 int64_t capture_time_ms) {
Erik Språng242e22b2015-05-11 10:17:43 +0200288 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000289 last_rtp_timestamp_ = rtp_timestamp;
290 if (capture_time_ms < 0) {
291 // We don't currently get a capture time from VoiceEngine.
Erik Språng242e22b2015-05-11 10:17:43 +0200292 last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000293 } else {
294 last_frame_capture_time_ms_ = capture_time_ms;
295 }
296}
297
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000298void RTCPSender::SetSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200299 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000300
Erik Språng242e22b2015-05-11 10:17:43 +0200301 if (ssrc_ != 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200302 // not first SetSSRC, probably due to a collision
303 // schedule a new RTCP report
304 // make sure that we send a RTP packet
Erik Språng242e22b2015-05-11 10:17:43 +0200305 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
Erik Språng61be2a42015-04-27 13:32:52 +0200306 }
Erik Språng242e22b2015-05-11 10:17:43 +0200307 ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000308}
309
Erik Språng61be2a42015-04-27 13:32:52 +0200310void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200311 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
312 remote_ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000313}
314
Peter Boström9ba52f82015-06-01 14:12:28 +0200315int32_t RTCPSender::SetCNAME(const char* c_name) {
316 if (!c_name)
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000317 return -1;
318
henrikg91d6ede2015-09-17 00:24:34 -0700319 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
Erik Språng242e22b2015-05-11 10:17:43 +0200320 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200321 cname_ = c_name;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000322 return 0;
323}
324
Erik Språng0ea42d32015-06-25 14:46:16 +0200325int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC, const char* c_name) {
326 assert(c_name);
henrikg91d6ede2015-09-17 00:24:34 -0700327 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
Erik Språng242e22b2015-05-11 10:17:43 +0200328 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200329 if (csrc_cnames_.size() >= kRtpCsrcSize)
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000330 return -1;
Erik Språng0ea42d32015-06-25 14:46:16 +0200331
332 csrc_cnames_[SSRC] = c_name;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000333 return 0;
334}
335
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000336int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
Erik Språng242e22b2015-05-11 10:17:43 +0200337 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200338 auto it = csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000339
Erik Språng242e22b2015-05-11 10:17:43 +0200340 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000341 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200342
Erik Språng242e22b2015-05-11 10:17:43 +0200343 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000344 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000345}
346
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000347bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
danilchap162abd32015-12-10 02:39:40 -0800348 /*
349 For audio we use a fix 5 sec interval
niklase@google.com470e71d2011-07-07 08:21:25 +0000350
danilchap162abd32015-12-10 02:39:40 -0800351 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
352 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
353 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000354
355
danilchap162abd32015-12-10 02:39:40 -0800356 From RFC 3550
niklase@google.com470e71d2011-07-07 08:21:25 +0000357
danilchap162abd32015-12-10 02:39:40 -0800358 MAX RTCP BW is 5% if the session BW
359 A send report is approximately 65 bytes inc CNAME
360 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000361
danilchap162abd32015-12-10 02:39:40 -0800362 The RECOMMENDED value for the reduced minimum in seconds is 360
363 divided by the session bandwidth in kilobits/second. This minimum
364 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
niklase@google.com470e71d2011-07-07 08:21:25 +0000365
danilchap162abd32015-12-10 02:39:40 -0800366 If the participant has not yet sent an RTCP packet (the variable
367 initial is true), the constant Tmin is set to 2.5 seconds, else it
368 is set to 5 seconds.
niklase@google.com470e71d2011-07-07 08:21:25 +0000369
danilchap162abd32015-12-10 02:39:40 -0800370 The interval between RTCP packets is varied randomly over the
371 range [0.5,1.5] times the calculated interval to avoid unintended
372 synchronization of all participants
niklase@google.com470e71d2011-07-07 08:21:25 +0000373
danilchap162abd32015-12-10 02:39:40 -0800374 if we send
375 If the participant is a sender (we_sent true), the constant C is
376 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
377 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
378 number of senders.
niklase@google.com470e71d2011-07-07 08:21:25 +0000379
danilchap162abd32015-12-10 02:39:40 -0800380 if we receive only
381 If we_sent is not true, the constant C is set
382 to the average RTCP packet size divided by 75% of the RTCP
383 bandwidth. The constant n is set to the number of receivers
384 (members - senders). If the number of senders is greater than
385 25%, senders and receivers are treated together.
niklase@google.com470e71d2011-07-07 08:21:25 +0000386
danilchap162abd32015-12-10 02:39:40 -0800387 reconsideration NOT required for peer-to-peer
388 "timer reconsideration" is
389 employed. This algorithm implements a simple back-off mechanism
390 which causes users to hold back RTCP packet transmission if the
391 group sizes are increasing.
niklase@google.com470e71d2011-07-07 08:21:25 +0000392
danilchap162abd32015-12-10 02:39:40 -0800393 n = number of members
394 C = avg_size/(rtcpBW/4)
niklase@google.com470e71d2011-07-07 08:21:25 +0000395
danilchap162abd32015-12-10 02:39:40 -0800396 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
niklase@google.com470e71d2011-07-07 08:21:25 +0000397
danilchap162abd32015-12-10 02:39:40 -0800398 4. The calculated interval T is set to a number uniformly distributed
399 between 0.5 and 1.5 times the deterministic calculated interval.
niklase@google.com470e71d2011-07-07 08:21:25 +0000400
danilchap162abd32015-12-10 02:39:40 -0800401 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
402 for the fact that the timer reconsideration algorithm converges to
403 a value of the RTCP bandwidth below the intended average
404 */
niklase@google.com470e71d2011-07-07 08:21:25 +0000405
Erik Språng242e22b2015-05-11 10:17:43 +0200406 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000407
Erik Språng242e22b2015-05-11 10:17:43 +0200408 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
xians@webrtc.org8738d272011-11-25 13:43:53 +0000409
pbosda903ea2015-10-02 02:36:56 -0700410 if (method_ == RtcpMode::kOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000411 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000412
Erik Språng242e22b2015-05-11 10:17:43 +0200413 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200414 // for video key-frames we want to send the RTCP before the large key-frame
415 // if we have a 100 ms margin
416 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
417 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000418
Erik Språng242e22b2015-05-11 10:17:43 +0200419 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200420 return true;
421 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200422 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200423 // wrap
424 return true;
425 }
426 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000427}
428
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000429int64_t RTCPSender::SendTimeOfSendReport(uint32_t sendReport) {
Erik Språng242e22b2015-05-11 10:17:43 +0200430 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000431
Erik Språng61be2a42015-04-27 13:32:52 +0200432 // This is only saved when we are the sender
Erik Språng242e22b2015-05-11 10:17:43 +0200433 if ((last_send_report_[0] == 0) || (sendReport == 0)) {
Erik Språng61be2a42015-04-27 13:32:52 +0200434 return 0; // will be ignored
435 } else {
436 for (int i = 0; i < RTCP_NUMBER_OF_SR; ++i) {
Erik Språng242e22b2015-05-11 10:17:43 +0200437 if (last_send_report_[i] == sendReport)
438 return last_rtcp_time_[i];
niklase@google.com470e71d2011-07-07 08:21:25 +0000439 }
Erik Språng61be2a42015-04-27 13:32:52 +0200440 }
441 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000442}
443
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000444bool RTCPSender::SendTimeOfXrRrReport(uint32_t mid_ntp,
445 int64_t* time_ms) const {
Erik Språng242e22b2015-05-11 10:17:43 +0200446 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000447
448 if (last_xr_rr_.empty()) {
449 return false;
450 }
451 std::map<uint32_t, int64_t>::const_iterator it = last_xr_rr_.find(mid_ntp);
452 if (it == last_xr_rr_.end()) {
453 return false;
454 }
455 *time_ms = it->second;
456 return true;
457}
458
Erik Språngf7c57762015-12-04 10:40:35 +0100459rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildSR(const RtcpContext& ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200460 for (int i = (RTCP_NUMBER_OF_SR - 2); i >= 0; i--) {
461 // shift old
Erik Språng242e22b2015-05-11 10:17:43 +0200462 last_send_report_[i + 1] = last_send_report_[i];
463 last_rtcp_time_[i + 1] = last_rtcp_time_[i];
Erik Språng61be2a42015-04-27 13:32:52 +0200464 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000465
Erik Språngf7c57762015-12-04 10:40:35 +0100466 last_rtcp_time_[0] = Clock::NtpToMs(ctx.ntp_sec_, ctx.ntp_frac_);
467 last_send_report_[0] = (ctx.ntp_sec_ << 16) + (ctx.ntp_frac_ >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000468
Erik Språng61be2a42015-04-27 13:32:52 +0200469 // The timestamp of this RTCP packet should be estimated as the timestamp of
470 // the frame being captured at this moment. We are calculating that
471 // timestamp as the last frame's timestamp + the time since the last frame
472 // was captured.
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200473 uint32_t rtp_timestamp =
474 start_timestamp_ + last_rtp_timestamp_ +
475 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) *
Erik Språngf7c57762015-12-04 10:40:35 +0100476 (ctx.feedback_state_.frequency_hz / 1000);
niklase@google.com470e71d2011-07-07 08:21:25 +0000477
Erik Språngf7c57762015-12-04 10:40:35 +0100478 rtcp::SenderReport* report = new rtcp::SenderReport();
479 report->From(ssrc_);
480 report->WithNtpSec(ctx.ntp_sec_);
481 report->WithNtpFrac(ctx.ntp_frac_);
482 report->WithRtpTimestamp(rtp_timestamp);
483 report->WithPacketCount(ctx.feedback_state_.packets_sent);
484 report->WithOctetCount(ctx.feedback_state_.media_bytes_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000485
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200486 for (auto it : report_blocks_)
Erik Språngf7c57762015-12-04 10:40:35 +0100487 report->WithReportBlock(it.second);
niklase@google.com470e71d2011-07-07 08:21:25 +0000488
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200489 report_blocks_.clear();
Erik Språngf7c57762015-12-04 10:40:35 +0100490
491 return rtc::scoped_ptr<rtcp::SenderReport>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000492}
493
Erik Språngf7c57762015-12-04 10:40:35 +0100494rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildSDES(
495 const RtcpContext& ctx) {
Erik Språng0ea42d32015-06-25 14:46:16 +0200496 size_t length_cname = cname_.length();
henrikg91d6ede2015-09-17 00:24:34 -0700497 RTC_CHECK_LT(length_cname, static_cast<size_t>(RTCP_CNAME_SIZE));
niklase@google.com470e71d2011-07-07 08:21:25 +0000498
Erik Språngf7c57762015-12-04 10:40:35 +0100499 rtcp::Sdes* sdes = new rtcp::Sdes();
500 sdes->WithCName(ssrc_, cname_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200501
502 for (const auto it : csrc_cnames_)
Erik Språngf7c57762015-12-04 10:40:35 +0100503 sdes->WithCName(it.first, it.second);
Erik Språng0ea42d32015-06-25 14:46:16 +0200504
Erik Språngf7c57762015-12-04 10:40:35 +0100505 return rtc::scoped_ptr<rtcp::Sdes>(sdes);
niklase@google.com470e71d2011-07-07 08:21:25 +0000506}
507
Erik Språngf7c57762015-12-04 10:40:35 +0100508rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildRR(const RtcpContext& ctx) {
509 rtcp::ReceiverReport* report = new rtcp::ReceiverReport();
510 report->From(ssrc_);
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200511 for (auto it : report_blocks_)
Erik Språngf7c57762015-12-04 10:40:35 +0100512 report->WithReportBlock(it.second);
Erik Språng61be2a42015-04-27 13:32:52 +0200513
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200514 report_blocks_.clear();
Erik Språngf7c57762015-12-04 10:40:35 +0100515 return rtc::scoped_ptr<rtcp::ReceiverReport>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000516}
517
Erik Språngf7c57762015-12-04 10:40:35 +0100518rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildPLI(const RtcpContext& ctx) {
519 rtcp::Pli* pli = new rtcp::Pli();
520 pli->From(ssrc_);
521 pli->To(remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200522
Erik Språng242e22b2015-05-11 10:17:43 +0200523 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
524 "RTCPSender::PLI");
525 ++packet_type_counter_.pli_packets;
526 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
527 ssrc_, packet_type_counter_.pli_packets);
528
Erik Språngf7c57762015-12-04 10:40:35 +0100529 return rtc::scoped_ptr<rtcp::Pli>(pli);
Erik Språng61be2a42015-04-27 13:32:52 +0200530}
531
Erik Språngf7c57762015-12-04 10:40:35 +0100532rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildFIR(const RtcpContext& ctx) {
533 if (!ctx.repeat_)
sprang62dae192015-08-05 02:35:35 -0700534 ++sequence_number_fir_; // Do not increase if repetition.
niklase@google.com470e71d2011-07-07 08:21:25 +0000535
Erik Språngf7c57762015-12-04 10:40:35 +0100536 rtcp::Fir* fir = new rtcp::Fir();
537 fir->From(ssrc_);
538 fir->To(remote_ssrc_);
539 fir->WithCommandSeqNum(sequence_number_fir_);
Erik Språng242e22b2015-05-11 10:17:43 +0200540
541 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
542 "RTCPSender::FIR");
543 ++packet_type_counter_.fir_packets;
544 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
545 ssrc_, packet_type_counter_.fir_packets);
546
Erik Språngf7c57762015-12-04 10:40:35 +0100547 return rtc::scoped_ptr<rtcp::Fir>(fir);
niklase@google.com470e71d2011-07-07 08:21:25 +0000548}
549
550/*
551 0 1 2 3
552 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
553 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
554 | First | Number | PictureID |
555 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
556*/
Erik Språngf7c57762015-12-04 10:40:35 +0100557rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildSLI(const RtcpContext& ctx) {
558 rtcp::Sli* sli = new rtcp::Sli();
559 sli->From(ssrc_);
560 sli->To(remote_ssrc_);
sprang0365a272015-08-11 01:02:37 -0700561 // Crop picture id to 6 least significant bits.
Erik Språngf7c57762015-12-04 10:40:35 +0100562 sli->WithPictureId(ctx.picture_id_ & 0x3F);
sprang0365a272015-08-11 01:02:37 -0700563
Erik Språngf7c57762015-12-04 10:40:35 +0100564 return rtc::scoped_ptr<rtcp::Sli>(sli);
niklase@google.com470e71d2011-07-07 08:21:25 +0000565}
566
567/*
568 0 1 2 3
569 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
570 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
571 | PB |0| Payload Type| Native RPSI bit string |
572 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
573 | defined per codec ... | Padding (0) |
574 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
575*/
576/*
577* Note: not generic made for VP8
578*/
Erik Språngf7c57762015-12-04 10:40:35 +0100579rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildRPSI(
580 const RtcpContext& ctx) {
581 if (ctx.feedback_state_.send_payload_type == 0xFF)
582 return nullptr;
Erik Språng242e22b2015-05-11 10:17:43 +0200583
Erik Språngf7c57762015-12-04 10:40:35 +0100584 rtcp::Rpsi* rpsi = new rtcp::Rpsi();
585 rpsi->From(ssrc_);
586 rpsi->To(remote_ssrc_);
587 rpsi->WithPayloadType(ctx.feedback_state_.send_payload_type);
588 rpsi->WithPictureId(ctx.picture_id_);
sprangcf7f54d2015-08-13 04:37:42 -0700589
Erik Språngf7c57762015-12-04 10:40:35 +0100590 return rtc::scoped_ptr<rtcp::Rpsi>(rpsi);
niklase@google.com470e71d2011-07-07 08:21:25 +0000591}
592
Erik Språngf7c57762015-12-04 10:40:35 +0100593rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildREMB(
594 const RtcpContext& ctx) {
595 rtcp::Remb* remb = new rtcp::Remb();
596 remb->From(ssrc_);
sprangdd4edc52015-08-21 04:21:51 -0700597 for (uint32_t ssrc : remb_ssrcs_)
Erik Språngf7c57762015-12-04 10:40:35 +0100598 remb->AppliesTo(ssrc);
599 remb->WithBitrateBps(remb_bitrate_);
Erik Språng61be2a42015-04-27 13:32:52 +0200600
Erik Språng242e22b2015-05-11 10:17:43 +0200601 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
602 "RTCPSender::REMB");
603
Erik Språngf7c57762015-12-04 10:40:35 +0100604 return rtc::scoped_ptr<rtcp::Remb>(remb);
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000605}
606
Erik Språng61be2a42015-04-27 13:32:52 +0200607void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
Erik Språng242e22b2015-05-11 10:17:43 +0200608 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
609 tmmbr_send_ = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000610}
611
Erik Språngf7c57762015-12-04 10:40:35 +0100612rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBR(
613 const RtcpContext& ctx) {
614 if (ctx.feedback_state_.module == nullptr)
615 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200616 // Before sending the TMMBR check the received TMMBN, only an owner is
617 // allowed to raise the bitrate:
618 // * If the sender is an owner of the TMMBN -> send TMMBR
619 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000620
Erik Språng61be2a42015-04-27 13:32:52 +0200621 // get current bounding set from RTCP receiver
622 bool tmmbrOwner = false;
623 // store in candidateSet, allocates one extra slot
Erik Språng242e22b2015-05-11 10:17:43 +0200624 TMMBRSet* candidateSet = tmmbr_help_.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000625
Erik Språng242e22b2015-05-11 10:17:43 +0200626 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
627 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
Erik Språng61be2a42015-04-27 13:32:52 +0200628 // since RTCPreceiver is not doing the reverse we should be fine
629 int32_t lengthOfBoundingSet =
danilchap6db6cdc2015-12-15 02:54:47 -0800630 ctx.feedback_state_.module->BoundingSet(&tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +0000631
Erik Språng61be2a42015-04-27 13:32:52 +0200632 if (lengthOfBoundingSet > 0) {
633 for (int32_t i = 0; i < lengthOfBoundingSet; i++) {
Erik Språng242e22b2015-05-11 10:17:43 +0200634 if (candidateSet->Tmmbr(i) == tmmbr_send_ &&
635 candidateSet->PacketOH(i) == packet_oh_send_) {
Erik Språngf7c57762015-12-04 10:40:35 +0100636 // Do not send the same tuple.
637 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200638 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000639 }
Erik Språng61be2a42015-04-27 13:32:52 +0200640 if (!tmmbrOwner) {
641 // use received bounding set as candidate set
642 // add current tuple
Erik Språng242e22b2015-05-11 10:17:43 +0200643 candidateSet->SetEntry(lengthOfBoundingSet, tmmbr_send_, packet_oh_send_,
644 ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200645 int numCandidates = lengthOfBoundingSet + 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000646
Erik Språng61be2a42015-04-27 13:32:52 +0200647 // find bounding set
Erik Språngf7c57762015-12-04 10:40:35 +0100648 TMMBRSet* boundingSet = nullptr;
Erik Språng242e22b2015-05-11 10:17:43 +0200649 int numBoundingSet = tmmbr_help_.FindTMMBRBoundingSet(boundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200650 if (numBoundingSet > 0 || numBoundingSet <= numCandidates)
Erik Språng242e22b2015-05-11 10:17:43 +0200651 tmmbrOwner = tmmbr_help_.IsOwner(ssrc_, numBoundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200652 if (!tmmbrOwner) {
Erik Språngf7c57762015-12-04 10:40:35 +0100653 // Did not enter bounding set, no meaning to send this request.
654 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200655 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000656 }
Erik Språng61be2a42015-04-27 13:32:52 +0200657 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000658
Erik Språngf7c57762015-12-04 10:40:35 +0100659 if (!tmmbr_send_)
660 return nullptr;
sprang81a3e602015-08-21 05:30:11 -0700661
Erik Språngf7c57762015-12-04 10:40:35 +0100662 rtcp::Tmmbr* tmmbr = new rtcp::Tmmbr();
663 tmmbr->From(ssrc_);
664 tmmbr->To(remote_ssrc_);
665 tmmbr->WithBitrateKbps(tmmbr_send_);
666 tmmbr->WithOverhead(packet_oh_send_);
667
668 return rtc::scoped_ptr<rtcp::Tmmbr>(tmmbr);
Erik Språng61be2a42015-04-27 13:32:52 +0200669}
670
Erik Språngf7c57762015-12-04 10:40:35 +0100671rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBN(
672 const RtcpContext& ctx) {
Erik Språng242e22b2015-05-11 10:17:43 +0200673 TMMBRSet* boundingSet = tmmbr_help_.BoundingSetToSend();
Erik Språngf7c57762015-12-04 10:40:35 +0100674 if (boundingSet == nullptr)
675 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200676
Erik Språngf7c57762015-12-04 10:40:35 +0100677 rtcp::Tmmbn* tmmbn = new rtcp::Tmmbn();
678 tmmbn->From(ssrc_);
sprangd83df502015-08-27 01:05:08 -0700679 for (uint32_t i = 0; i < boundingSet->lengthOfSet(); i++) {
680 if (boundingSet->Tmmbr(i) > 0) {
Erik Språngf7c57762015-12-04 10:40:35 +0100681 tmmbn->WithTmmbr(boundingSet->Ssrc(i), boundingSet->Tmmbr(i),
682 boundingSet->PacketOH(i));
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000683 }
Erik Språng61be2a42015-04-27 13:32:52 +0200684 }
sprangd83df502015-08-27 01:05:08 -0700685
Erik Språngf7c57762015-12-04 10:40:35 +0100686 return rtc::scoped_ptr<rtcp::Tmmbn>(tmmbn);
niklase@google.com470e71d2011-07-07 08:21:25 +0000687}
688
Erik Språngf7c57762015-12-04 10:40:35 +0100689rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildAPP(const RtcpContext& ctx) {
690 rtcp::App* app = new rtcp::App();
691 app->From(ssrc_);
692 app->WithSubType(app_sub_type_);
693 app->WithName(app_name_);
694 app->WithData(app_data_.get(), app_length_);
Erik Språng521875a2015-09-01 10:11:16 +0200695
Erik Språngf7c57762015-12-04 10:40:35 +0100696 return rtc::scoped_ptr<rtcp::App>(app);
Erik Språng61be2a42015-04-27 13:32:52 +0200697}
698
Erik Språngf7c57762015-12-04 10:40:35 +0100699rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildNACK(
700 const RtcpContext& ctx) {
701 rtcp::Nack* nack = new rtcp::Nack();
702 nack->From(ssrc_);
703 nack->To(remote_ssrc_);
704 nack->WithList(ctx.nack_list_, ctx.nack_size_);
Erik Språng61be2a42015-04-27 13:32:52 +0200705
706 // Report stats.
707 NACKStringBuilder stringBuilder;
Erik Språngf7c57762015-12-04 10:40:35 +0100708 for (int idx = 0; idx < ctx.nack_size_; ++idx) {
709 stringBuilder.PushNACK(ctx.nack_list_[idx]);
710 nack_stats_.ReportRequest(ctx.nack_list_[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +0200711 }
Erik Språng61be2a42015-04-27 13:32:52 +0200712 packet_type_counter_.nack_requests = nack_stats_.requests();
713 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +0200714
715 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
716 "RTCPSender::NACK", "nacks",
717 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
718 ++packet_type_counter_.nack_packets;
719 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
720 ssrc_, packet_type_counter_.nack_packets);
721
Erik Språngf7c57762015-12-04 10:40:35 +0100722 return rtc::scoped_ptr<rtcp::Nack>(nack);
Erik Språng61be2a42015-04-27 13:32:52 +0200723}
724
Erik Språngf7c57762015-12-04 10:40:35 +0100725rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildBYE(const RtcpContext& ctx) {
726 rtcp::Bye* bye = new rtcp::Bye();
727 bye->From(ssrc_);
sprangd8ee4f92015-08-24 03:25:19 -0700728 for (uint32_t csrc : csrcs_)
Erik Språngf7c57762015-12-04 10:40:35 +0100729 bye->WithCsrc(csrc);
sprangd8ee4f92015-08-24 03:25:19 -0700730
Erik Språngf7c57762015-12-04 10:40:35 +0100731 return rtc::scoped_ptr<rtcp::Bye>(bye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000732}
733
Erik Språngf7c57762015-12-04 10:40:35 +0100734rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildReceiverReferenceTime(
735 const RtcpContext& ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200736 if (last_xr_rr_.size() >= RTCP_NUMBER_OF_SR)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000737 last_xr_rr_.erase(last_xr_rr_.begin());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000738 last_xr_rr_.insert(std::pair<uint32_t, int64_t>(
Erik Språngf7c57762015-12-04 10:40:35 +0100739 RTCPUtility::MidNtp(ctx.ntp_sec_, ctx.ntp_frac_),
740 Clock::NtpToMs(ctx.ntp_sec_, ctx.ntp_frac_)));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000741
Erik Språngf7c57762015-12-04 10:40:35 +0100742 rtcp::Xr* xr = new rtcp::Xr();
743 xr->From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000744
Erik Språngca28fdc2015-08-31 14:00:50 +0200745 rtcp::Rrtr rrtr;
Danil Chapovalovfc47ed62015-12-07 14:46:35 +0100746 rrtr.WithNtp(NtpTime(ctx.ntp_sec_, ctx.ntp_frac_));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000747
Erik Språngf7c57762015-12-04 10:40:35 +0100748 xr->WithRrtr(&rrtr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000749
Erik Språngca28fdc2015-08-31 14:00:50 +0200750 // TODO(sprang): Merge XR report sending to contain all of RRTR, DLRR, VOIP?
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000751
Erik Språngf7c57762015-12-04 10:40:35 +0100752 return rtc::scoped_ptr<rtcp::Xr>(xr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000753}
754
Erik Språngf7c57762015-12-04 10:40:35 +0100755rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildDlrr(
756 const RtcpContext& ctx) {
757 rtcp::Xr* xr = new rtcp::Xr();
758 xr->From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000759
Erik Språngca28fdc2015-08-31 14:00:50 +0200760 rtcp::Dlrr dlrr;
Erik Språngf7c57762015-12-04 10:40:35 +0100761 const RtcpReceiveTimeInfo& info = ctx.feedback_state_.last_xr_rr;
Erik Språngca28fdc2015-08-31 14:00:50 +0200762 dlrr.WithDlrrItem(info.sourceSSRC, info.lastRR, info.delaySinceLastRR);
763
Erik Språngf7c57762015-12-04 10:40:35 +0100764 xr->WithDlrr(&dlrr);
Erik Språngca28fdc2015-08-31 14:00:50 +0200765
Erik Språngf7c57762015-12-04 10:40:35 +0100766 return rtc::scoped_ptr<rtcp::Xr>(xr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000767}
768
Erik Språng242e22b2015-05-11 10:17:43 +0200769// TODO(sprang): Add a unit test for this, or remove if the code isn't used.
Erik Språngf7c57762015-12-04 10:40:35 +0100770rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildVoIPMetric(
771 const RtcpContext& context) {
772 rtcp::Xr* xr = new rtcp::Xr();
773 xr->From(ssrc_);
Erik Språngca28fdc2015-08-31 14:00:50 +0200774
775 rtcp::VoipMetric voip;
776 voip.To(remote_ssrc_);
danilchap91941ae2015-12-15 07:06:36 -0800777 voip.WithVoipMetric(xr_voip_metric_);
Erik Språngca28fdc2015-08-31 14:00:50 +0200778
Erik Språngf7c57762015-12-04 10:40:35 +0100779 xr->WithVoipMetric(&voip);
Erik Språngca28fdc2015-08-31 14:00:50 +0200780
Erik Språngf7c57762015-12-04 10:40:35 +0100781 return rtc::scoped_ptr<rtcp::Xr>(xr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000782}
783
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000784int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200785 RTCPPacketType packetType,
786 int32_t nack_size,
787 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000788 bool repeat,
789 uint64_t pictureID) {
Erik Språng242e22b2015-05-11 10:17:43 +0200790 return SendCompoundRTCP(
791 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
792 nack_size, nack_list, repeat, pictureID);
793}
794
795int32_t RTCPSender::SendCompoundRTCP(
796 const FeedbackState& feedback_state,
Erik Språngf7c57762015-12-04 10:40:35 +0100797 const std::set<RTCPPacketType>& packet_types,
Erik Språng242e22b2015-05-11 10:17:43 +0200798 int32_t nack_size,
799 const uint16_t* nack_list,
800 bool repeat,
801 uint64_t pictureID) {
Erik Språngf7c57762015-12-04 10:40:35 +0100802 PacketContainer container(transport_);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000803 {
Erik Språng242e22b2015-05-11 10:17:43 +0200804 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
pbosda903ea2015-10-02 02:36:56 -0700805 if (method_ == RtcpMode::kOff) {
Erik Språng61be2a42015-04-27 13:32:52 +0200806 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
807 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +0000808 }
Erik Språngf7c57762015-12-04 10:40:35 +0100809
810 // We need to send our NTP even if we haven't received any reports.
811 uint32_t ntp_sec;
812 uint32_t ntp_frac;
813 clock_->CurrentNtp(ntp_sec, ntp_frac);
814 RtcpContext context(feedback_state, nack_size, nack_list, repeat, pictureID,
815 ntp_sec, ntp_frac, &container);
816
817 PrepareReport(packet_types, feedback_state);
818
819 auto it = report_flags_.begin();
820 while (it != report_flags_.end()) {
821 auto builder_it = builders_.find(it->type);
822 RTC_DCHECK(builder_it != builders_.end());
823 if (it->is_volatile) {
824 report_flags_.erase(it++);
825 } else {
826 ++it;
827 }
828
829 BuilderFunc func = builder_it->second;
830 rtc::scoped_ptr<rtcp::RtcpPacket> packet = (this->*func)(context);
831 if (packet.get() == nullptr)
832 return -1;
833 container.Append(packet.release());
834 }
835
836 if (packet_type_counter_observer_ != nullptr) {
837 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
838 remote_ssrc_, packet_type_counter_);
839 }
840
841 RTC_DCHECK(AllVolatileFlagsConsumed());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000842 }
Erik Språng61be2a42015-04-27 13:32:52 +0200843
Erik Språngf7c57762015-12-04 10:40:35 +0100844 size_t bytes_sent = container.SendPackets();
845 return bytes_sent == 0 ? -1 : 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000846}
847
Erik Språngf7c57762015-12-04 10:40:35 +0100848void RTCPSender::PrepareReport(const std::set<RTCPPacketType>& packetTypes,
849 const FeedbackState& feedback_state) {
Erik Språng242e22b2015-05-11 10:17:43 +0200850 // Add all flags as volatile. Non volatile entries will not be overwritten
851 // and all new volatile flags added will be consumed by the end of this call.
852 SetFlags(packetTypes, true);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000853
Erik Språng61be2a42015-04-27 13:32:52 +0200854 if (packet_type_counter_.first_packet_time_ms == -1)
Erik Språng242e22b2015-05-11 10:17:43 +0200855 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språng61be2a42015-04-27 13:32:52 +0200856
Erik Språng242e22b2015-05-11 10:17:43 +0200857 bool generate_report;
858 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
859 // Report type already explicitly set, don't automatically populate.
860 generate_report = true;
henrikg91d6ede2015-09-17 00:24:34 -0700861 RTC_DCHECK(ConsumeFlag(kRtcpReport) == false);
Erik Språng242e22b2015-05-11 10:17:43 +0200862 } else {
863 generate_report =
pbosda903ea2015-10-02 02:36:56 -0700864 (ConsumeFlag(kRtcpReport) && method_ == RtcpMode::kReducedSize) ||
865 method_ == RtcpMode::kCompound;
Erik Språng242e22b2015-05-11 10:17:43 +0200866 if (generate_report)
867 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000868 }
869
Erik Språng0ea42d32015-06-25 14:46:16 +0200870 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
Erik Språng242e22b2015-05-11 10:17:43 +0200871 SetFlag(kRtcpSdes, true);
872
Erik Språng242e22b2015-05-11 10:17:43 +0200873 if (generate_report) {
874 if (!sending_ && xr_send_receiver_reference_time_enabled_)
875 SetFlag(kRtcpXrReceiverReferenceTime, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200876 if (feedback_state.has_last_xr_rr)
Erik Språng242e22b2015-05-11 10:17:43 +0200877 SetFlag(kRtcpXrDlrrReportBlock, true);
878
879 // generate next time to send an RTCP report
danilchap47a740b2015-12-15 00:30:07 -0800880 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000881
danilchap47a740b2015-12-15 00:30:07 -0800882 if (!audio_) {
Erik Språng242e22b2015-05-11 10:17:43 +0200883 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200884 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
885 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
886 if (send_bitrate_kbit != 0)
887 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000888 }
Erik Språng61be2a42015-04-27 13:32:52 +0200889 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
890 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
Erik Språng61be2a42015-04-27 13:32:52 +0200891 }
danilchap47a740b2015-12-15 00:30:07 -0800892 // The interval between RTCP packets is varied randomly over the
893 // range [1/2,3/2] times the calculated interval.
894 uint32_t timeToNext =
895 random_.Rand(minIntervalMs * 1 / 2, minIntervalMs * 3 / 2);
Erik Språng242e22b2015-05-11 10:17:43 +0200896 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000897
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000898 StatisticianMap statisticians =
899 receive_statistics_->GetActiveStatisticians();
danilchapa72e7342015-12-22 08:07:45 -0800900 RTC_DCHECK(report_blocks_.empty());
901 for (auto& it : statisticians) {
902 AddReportBlock(feedback_state, it.first, it.second);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000903 }
904 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000905}
906
danilchapa72e7342015-12-22 08:07:45 -0800907bool RTCPSender::AddReportBlock(const FeedbackState& feedback_state,
908 uint32_t ssrc,
909 StreamStatistician* statistician) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000910 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000911 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000912 if (!statistician->GetStatistics(&stats, true))
913 return false;
danilchapa72e7342015-12-22 08:07:45 -0800914
915 if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) {
916 LOG(LS_WARNING) << "Too many report blocks.";
917 return false;
918 }
919 RTC_DCHECK(report_blocks_.find(ssrc) == report_blocks_.end());
920 rtcp::ReportBlock* block = &report_blocks_[ssrc];
921 block->To(ssrc);
922 block->WithFractionLost(stats.fraction_lost);
923 if (!block->WithCumulativeLost(stats.cumulative_lost)) {
924 report_blocks_.erase(ssrc);
925 LOG(LS_WARNING) << "Cumulative lost is oversized.";
926 return false;
927 }
928 block->WithExtHighestSeqNum(stats.extended_max_sequence_number);
929 block->WithJitter(stats.jitter);
930 block->WithLastSr(feedback_state.remote_sr);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000931
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200932 // TODO(sprang): Do we really need separate time stamps for each report?
933 // Get our NTP as late as possible to avoid a race.
934 uint32_t ntp_secs;
935 uint32_t ntp_frac;
936 clock_->CurrentNtp(ntp_secs, ntp_frac);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000937
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200938 // Delay since last received report.
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000939 if ((feedback_state.last_rr_ntp_secs != 0) ||
940 (feedback_state.last_rr_ntp_frac != 0)) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200941 // Get the 16 lowest bits of seconds and the 16 highest bits of fractions.
942 uint32_t now = ntp_secs & 0x0000FFFF;
Erik Språng61be2a42015-04-27 13:32:52 +0200943 now <<= 16;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200944 now += (ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000945
Erik Språng61be2a42015-04-27 13:32:52 +0200946 uint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
947 receiveTime <<= 16;
948 receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000949
danilchapa72e7342015-12-22 08:07:45 -0800950 block->WithDelayLastSr(now - receiveTime);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000951 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000952 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000953}
954
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000955void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
956 assert(csrcs.size() <= kRtpCsrcSize);
Erik Språng242e22b2015-05-11 10:17:43 +0200957 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000958 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +0000959}
960
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000961int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
962 uint32_t name,
963 const uint8_t* data,
964 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +0200965 if (length % 4 != 0) {
966 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
967 return -1;
968 }
Erik Språng242e22b2015-05-11 10:17:43 +0200969 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000970
Erik Språng242e22b2015-05-11 10:17:43 +0200971 SetFlag(kRtcpApp, true);
972 app_sub_type_ = subType;
973 app_name_ = name;
974 app_data_.reset(new uint8_t[length]);
975 app_length_ = length;
976 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +0200977 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000978}
979
Erik Språng61be2a42015-04-27 13:32:52 +0200980int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
Erik Språng242e22b2015-05-11 10:17:43 +0200981 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
982 memcpy(&xr_voip_metric_, VoIPMetric, sizeof(RTCPVoIPMetric));
niklase@google.com470e71d2011-07-07 08:21:25 +0000983
Erik Språng242e22b2015-05-11 10:17:43 +0200984 SetFlag(kRtcpXrVoipMetric, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200985 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000986}
987
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000988void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200989 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
990 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000991}
992
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000993bool RTCPSender::RtcpXrReceiverReferenceTime() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200994 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
995 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000996}
997
niklase@google.com470e71d2011-07-07 08:21:25 +0000998// no callbacks allowed inside this function
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000999int32_t RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
1000 uint32_t maxBitrateKbit) {
Erik Språng242e22b2015-05-11 10:17:43 +02001001 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +00001002
Erik Språng242e22b2015-05-11 10:17:43 +02001003 if (0 == tmmbr_help_.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit)) {
1004 SetFlag(kRtcpTmmbn, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001005 return 0;
1006 }
1007 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001008}
Erik Språng61be2a42015-04-27 13:32:52 +02001009
Erik Språng242e22b2015-05-11 10:17:43 +02001010void RTCPSender::SetFlag(RTCPPacketType type, bool is_volatile) {
1011 report_flags_.insert(ReportFlag(type, is_volatile));
1012}
1013
1014void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
1015 bool is_volatile) {
1016 for (RTCPPacketType type : types)
1017 SetFlag(type, is_volatile);
1018}
1019
1020bool RTCPSender::IsFlagPresent(RTCPPacketType type) const {
1021 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
1022}
1023
1024bool RTCPSender::ConsumeFlag(RTCPPacketType type, bool forced) {
1025 auto it = report_flags_.find(ReportFlag(type, false));
1026 if (it == report_flags_.end())
1027 return false;
1028 if (it->is_volatile || forced)
1029 report_flags_.erase((it));
1030 return true;
1031}
1032
1033bool RTCPSender::AllVolatileFlagsConsumed() const {
1034 for (const ReportFlag& flag : report_flags_) {
1035 if (flag.is_volatile)
1036 return false;
1037 }
1038 return true;
1039}
1040
sprang233bd872015-09-08 13:25:16 -07001041bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
sprang233bd872015-09-08 13:25:16 -07001042 class Sender : public rtcp::RtcpPacket::PacketReadyCallback {
1043 public:
danilchap6db6cdc2015-12-15 02:54:47 -08001044 explicit Sender(Transport* transport)
Peter Boströmac547a62015-09-17 23:03:57 +02001045 : transport_(transport), send_failure_(false) {}
sprang233bd872015-09-08 13:25:16 -07001046
1047 void OnPacketReady(uint8_t* data, size_t length) override {
pbos2d566682015-09-28 09:59:31 -07001048 if (!transport_->SendRtcp(data, length))
sprang233bd872015-09-08 13:25:16 -07001049 send_failure_ = true;
1050 }
1051
1052 Transport* const transport_;
sprang233bd872015-09-08 13:25:16 -07001053 bool send_failure_;
sprang86fd9ed2015-09-29 04:45:43 -07001054 } sender(transport_);
sprang233bd872015-09-08 13:25:16 -07001055
1056 uint8_t buffer[IP_PACKET_SIZE];
1057 return packet.BuildExternalBuffer(buffer, IP_PACKET_SIZE, &sender) &&
1058 !sender.send_failure_;
1059}
1060
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001061} // namespace webrtc