blob: c29ab85eb22a4e8abfde5959c5f095ea1ef06a0d [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"
sprang233bd872015-09-08 13:25:16 -070030#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
tommie4f96502015-10-20 23:00:48 -070031#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010032#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000033
niklase@google.com470e71d2011-07-07 08:21:25 +000034namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000035
36using RTCPUtility::RTCPCnameInformation;
37
Erik Språng61be2a42015-04-27 13:32:52 +020038NACKStringBuilder::NACKStringBuilder()
danilchap162abd32015-12-10 02:39:40 -080039 : stream_(""), count_(0), prevNack_(0), consecutive_(false) {}
edjee@google.com79b02892013-04-04 19:43:34 +000040
pbos@webrtc.orgf3e4cee2013-07-31 15:17:19 +000041NACKStringBuilder::~NACKStringBuilder() {}
42
danilchap162abd32015-12-10 02:39:40 -080043void NACKStringBuilder::PushNACK(uint16_t nack) {
Erik Språng242e22b2015-05-11 10:17:43 +020044 if (count_ == 0) {
45 stream_ << nack;
46 } else if (nack == prevNack_ + 1) {
47 consecutive_ = true;
Erik Språng61be2a42015-04-27 13:32:52 +020048 } else {
Erik Språng242e22b2015-05-11 10:17:43 +020049 if (consecutive_) {
50 stream_ << "-" << prevNack_;
51 consecutive_ = false;
edjee@google.com79b02892013-04-04 19:43:34 +000052 }
Erik Språng242e22b2015-05-11 10:17:43 +020053 stream_ << "," << nack;
Erik Språng61be2a42015-04-27 13:32:52 +020054 }
Erik Språng242e22b2015-05-11 10:17:43 +020055 count_++;
56 prevNack_ = nack;
edjee@google.com79b02892013-04-04 19:43:34 +000057}
58
Erik Språng61be2a42015-04-27 13:32:52 +020059std::string NACKStringBuilder::GetResult() {
Erik Språng242e22b2015-05-11 10:17:43 +020060 if (consecutive_) {
61 stream_ << "-" << prevNack_;
62 consecutive_ = false;
Erik Språng61be2a42015-04-27 13:32:52 +020063 }
Erik Språng242e22b2015-05-11 10:17:43 +020064 return stream_.str();
edjee@google.com79b02892013-04-04 19:43:34 +000065}
66
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000067RTCPSender::FeedbackState::FeedbackState()
68 : send_payload_type(0),
69 frequency_hz(0),
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +000070 packets_sent(0),
71 media_bytes_sent(0),
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000072 send_bitrate(0),
73 last_rr_ntp_secs(0),
74 last_rr_ntp_frac(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000075 remote_sr(0),
Erik Språng61be2a42015-04-27 13:32:52 +020076 has_last_xr_rr(false),
danilchap162abd32015-12-10 02:39:40 -080077 module(nullptr) {}
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000078
Erik Språngf7c57762015-12-04 10:40:35 +010079class PacketContainer : public rtcp::Empty,
80 public rtcp::RtcpPacket::PacketReadyCallback {
81 public:
82 explicit PacketContainer(Transport* transport)
83 : transport_(transport), bytes_sent_(0) {}
84 virtual ~PacketContainer() {
85 for (RtcpPacket* packet : appended_packets_)
86 delete packet;
87 }
88
89 void OnPacketReady(uint8_t* data, size_t length) override {
90 if (transport_->SendRtcp(data, length))
91 bytes_sent_ += length;
92 }
93
94 size_t SendPackets() {
95 rtcp::Empty::Build(this);
96 return bytes_sent_;
97 }
98
99 private:
100 Transport* transport_;
101 size_t bytes_sent_;
102};
103
104class RTCPSender::RtcpContext {
105 public:
Erik Språng242e22b2015-05-11 10:17:43 +0200106 RtcpContext(const FeedbackState& feedback_state,
107 int32_t nack_size,
108 const uint16_t* nack_list,
109 bool repeat,
110 uint64_t picture_id,
Erik Språngf7c57762015-12-04 10:40:35 +0100111 uint32_t ntp_sec,
112 uint32_t ntp_frac,
113 PacketContainer* container)
114 : feedback_state_(feedback_state),
115 nack_size_(nack_size),
116 nack_list_(nack_list),
117 repeat_(repeat),
118 picture_id_(picture_id),
119 ntp_sec_(ntp_sec),
120 ntp_frac_(ntp_frac),
121 container_(container) {}
Erik Språng242e22b2015-05-11 10:17:43 +0200122
Erik Språngf7c57762015-12-04 10:40:35 +0100123 virtual ~RtcpContext() {}
Erik Språng242e22b2015-05-11 10:17:43 +0200124
Erik Språngf7c57762015-12-04 10:40:35 +0100125 const FeedbackState& feedback_state_;
126 const int32_t nack_size_;
127 const uint16_t* nack_list_;
128 const bool repeat_;
129 const uint64_t picture_id_;
130 const uint32_t ntp_sec_;
131 const uint32_t ntp_frac_;
Erik Språng242e22b2015-05-11 10:17:43 +0200132
Erik Språngf7c57762015-12-04 10:40:35 +0100133 PacketContainer* const container_;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200134};
135
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000136RTCPSender::RTCPSender(
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000137 bool audio,
138 Clock* clock,
139 ReceiveStatistics* receive_statistics,
sprang86fd9ed2015-09-29 04:45:43 -0700140 RtcpPacketTypeCounterObserver* packet_type_counter_observer,
141 Transport* outgoing_transport)
Peter Boströmac547a62015-09-17 23:03:57 +0200142 : audio_(audio),
Erik Språng242e22b2015-05-11 10:17:43 +0200143 clock_(clock),
danilchap47a740b2015-12-15 00:30:07 -0800144 random_(clock_->TimeInMicroseconds()),
pbosda903ea2015-10-02 02:36:56 -0700145 method_(RtcpMode::kOff),
sprang86fd9ed2015-09-29 04:45:43 -0700146 transport_(outgoing_transport),
niklase@google.com470e71d2011-07-07 08:21:25 +0000147
Erik Språng242e22b2015-05-11 10:17:43 +0200148 critical_section_rtcp_sender_(
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000149 CriticalSectionWrapper::CreateCriticalSection()),
Erik Språng242e22b2015-05-11 10:17:43 +0200150 using_nack_(false),
151 sending_(false),
152 remb_enabled_(false),
Erik Språng242e22b2015-05-11 10:17:43 +0200153 next_time_to_send_rtcp_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000154 start_timestamp_(0),
155 last_rtp_timestamp_(0),
156 last_frame_capture_time_ms_(-1),
Erik Språng242e22b2015-05-11 10:17:43 +0200157 ssrc_(0),
158 remote_ssrc_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000159 receive_statistics_(receive_statistics),
niklase@google.com470e71d2011-07-07 08:21:25 +0000160
Erik Språng242e22b2015-05-11 10:17:43 +0200161 sequence_number_fir_(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000162
Erik Språng242e22b2015-05-11 10:17:43 +0200163 remb_bitrate_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000164
Erik Språng242e22b2015-05-11 10:17:43 +0200165 tmmbr_help_(),
166 tmmbr_send_(0),
167 packet_oh_send_(0),
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000168
Erik Språng242e22b2015-05-11 10:17:43 +0200169 app_sub_type_(0),
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200170 app_name_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200171 app_data_(nullptr),
172 app_length_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000173
Erik Språng242e22b2015-05-11 10:17:43 +0200174 xr_send_receiver_reference_time_enabled_(false),
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000175 packet_type_counter_observer_(packet_type_counter_observer) {
Erik Språng242e22b2015-05-11 10:17:43 +0200176 memset(last_send_report_, 0, sizeof(last_send_report_));
177 memset(last_rtcp_time_, 0, sizeof(last_rtcp_time_));
sprang86fd9ed2015-09-29 04:45:43 -0700178 RTC_DCHECK(transport_ != nullptr);
Erik Språng242e22b2015-05-11 10:17:43 +0200179
180 builders_[kRtcpSr] = &RTCPSender::BuildSR;
181 builders_[kRtcpRr] = &RTCPSender::BuildRR;
Erik Språng0ea42d32015-06-25 14:46:16 +0200182 builders_[kRtcpSdes] = &RTCPSender::BuildSDES;
Erik Språng242e22b2015-05-11 10:17:43 +0200183 builders_[kRtcpPli] = &RTCPSender::BuildPLI;
184 builders_[kRtcpFir] = &RTCPSender::BuildFIR;
185 builders_[kRtcpSli] = &RTCPSender::BuildSLI;
186 builders_[kRtcpRpsi] = &RTCPSender::BuildRPSI;
187 builders_[kRtcpRemb] = &RTCPSender::BuildREMB;
188 builders_[kRtcpBye] = &RTCPSender::BuildBYE;
189 builders_[kRtcpApp] = &RTCPSender::BuildAPP;
190 builders_[kRtcpTmmbr] = &RTCPSender::BuildTMMBR;
191 builders_[kRtcpTmmbn] = &RTCPSender::BuildTMMBN;
192 builders_[kRtcpNack] = &RTCPSender::BuildNACK;
193 builders_[kRtcpXrVoipMetric] = &RTCPSender::BuildVoIPMetric;
194 builders_[kRtcpXrReceiverReferenceTime] =
195 &RTCPSender::BuildReceiverReferenceTime;
196 builders_[kRtcpXrDlrrReportBlock] = &RTCPSender::BuildDlrr;
niklase@google.com470e71d2011-07-07 08:21:25 +0000197}
198
danilchap162abd32015-12-10 02:39:40 -0800199RTCPSender::~RTCPSender() {}
niklase@google.com470e71d2011-07-07 08:21:25 +0000200
pbosda903ea2015-10-02 02:36:56 -0700201RtcpMode RTCPSender::Status() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200202 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
203 return method_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000204}
205
pbosda903ea2015-10-02 02:36:56 -0700206void RTCPSender::SetRTCPStatus(RtcpMode method) {
Erik Språng242e22b2015-05-11 10:17:43 +0200207 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
208 method_ = method;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000209
pbosda903ea2015-10-02 02:36:56 -0700210 if (method == RtcpMode::kOff)
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000211 return;
Erik Språng242e22b2015-05-11 10:17:43 +0200212 next_time_to_send_rtcp_ =
213 clock_->TimeInMilliseconds() +
214 (audio_ ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000215}
216
Erik Språng61be2a42015-04-27 13:32:52 +0200217bool RTCPSender::Sending() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200218 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
219 return sending_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000220}
221
Erik Språng61be2a42015-04-27 13:32:52 +0200222int32_t RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
223 bool sending) {
224 bool sendRTCPBye = false;
225 {
Erik Språng242e22b2015-05-11 10:17:43 +0200226 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000227
pbosda903ea2015-10-02 02:36:56 -0700228 if (method_ != RtcpMode::kOff) {
Erik Språng242e22b2015-05-11 10:17:43 +0200229 if (sending == false && sending_ == true) {
Erik Språng61be2a42015-04-27 13:32:52 +0200230 // Trigger RTCP bye
231 sendRTCPBye = true;
232 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000233 }
Erik Språng242e22b2015-05-11 10:17:43 +0200234 sending_ = sending;
Erik Språng61be2a42015-04-27 13:32:52 +0200235 }
236 if (sendRTCPBye)
237 return SendRTCP(feedback_state, kRtcpBye);
238 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000239}
240
Erik Språng61be2a42015-04-27 13:32:52 +0200241bool RTCPSender::REMB() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200242 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
243 return remb_enabled_;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000244}
245
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000246void RTCPSender::SetREMBStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200247 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
248 remb_enabled_ = enable;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000249}
250
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000251void RTCPSender::SetREMBData(uint32_t bitrate,
252 const std::vector<uint32_t>& ssrcs) {
Erik Språng242e22b2015-05-11 10:17:43 +0200253 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
254 remb_bitrate_ = bitrate;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000255 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000256
Erik Språng242e22b2015-05-11 10:17:43 +0200257 if (remb_enabled_)
258 SetFlag(kRtcpRemb, false);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000259 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
260 // throttled by the caller.
Erik Språng242e22b2015-05-11 10:17:43 +0200261 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000262}
263
Erik Språng61be2a42015-04-27 13:32:52 +0200264bool RTCPSender::TMMBR() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200265 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
266 return IsFlagPresent(RTCPPacketType::kRtcpTmmbr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000267}
268
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000269void RTCPSender::SetTMMBRStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200270 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
271 if (enable) {
272 SetFlag(RTCPPacketType::kRtcpTmmbr, false);
273 } else {
274 ConsumeFlag(RTCPPacketType::kRtcpTmmbr, true);
275 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000276}
277
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000278void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
Erik Språng242e22b2015-05-11 10:17:43 +0200279 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000280 start_timestamp_ = start_timestamp;
281}
282
283void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
284 int64_t capture_time_ms) {
Erik Språng242e22b2015-05-11 10:17:43 +0200285 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000286 last_rtp_timestamp_ = rtp_timestamp;
287 if (capture_time_ms < 0) {
288 // We don't currently get a capture time from VoiceEngine.
Erik Språng242e22b2015-05-11 10:17:43 +0200289 last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000290 } else {
291 last_frame_capture_time_ms_ = capture_time_ms;
292 }
293}
294
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000295void RTCPSender::SetSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200296 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000297
Erik Språng242e22b2015-05-11 10:17:43 +0200298 if (ssrc_ != 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200299 // not first SetSSRC, probably due to a collision
300 // schedule a new RTCP report
301 // make sure that we send a RTP packet
Erik Språng242e22b2015-05-11 10:17:43 +0200302 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
Erik Språng61be2a42015-04-27 13:32:52 +0200303 }
Erik Språng242e22b2015-05-11 10:17:43 +0200304 ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000305}
306
Erik Språng61be2a42015-04-27 13:32:52 +0200307void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200308 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
309 remote_ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000310}
311
Peter Boström9ba52f82015-06-01 14:12:28 +0200312int32_t RTCPSender::SetCNAME(const char* c_name) {
313 if (!c_name)
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000314 return -1;
315
henrikg91d6ede2015-09-17 00:24:34 -0700316 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
Erik Språng242e22b2015-05-11 10:17:43 +0200317 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200318 cname_ = c_name;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000319 return 0;
320}
321
Erik Språng0ea42d32015-06-25 14:46:16 +0200322int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC, const char* c_name) {
323 assert(c_name);
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 if (csrc_cnames_.size() >= kRtpCsrcSize)
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000327 return -1;
Erik Språng0ea42d32015-06-25 14:46:16 +0200328
329 csrc_cnames_[SSRC] = c_name;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000330 return 0;
331}
332
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000333int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
Erik Språng242e22b2015-05-11 10:17:43 +0200334 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200335 auto it = csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000336
Erik Språng242e22b2015-05-11 10:17:43 +0200337 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000338 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200339
Erik Språng242e22b2015-05-11 10:17:43 +0200340 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000341 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000342}
343
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000344bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
danilchap162abd32015-12-10 02:39:40 -0800345 /*
346 For audio we use a fix 5 sec interval
niklase@google.com470e71d2011-07-07 08:21:25 +0000347
danilchap162abd32015-12-10 02:39:40 -0800348 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
349 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
350 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000351
352
danilchap162abd32015-12-10 02:39:40 -0800353 From RFC 3550
niklase@google.com470e71d2011-07-07 08:21:25 +0000354
danilchap162abd32015-12-10 02:39:40 -0800355 MAX RTCP BW is 5% if the session BW
356 A send report is approximately 65 bytes inc CNAME
357 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000358
danilchap162abd32015-12-10 02:39:40 -0800359 The RECOMMENDED value for the reduced minimum in seconds is 360
360 divided by the session bandwidth in kilobits/second. This minimum
361 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
niklase@google.com470e71d2011-07-07 08:21:25 +0000362
danilchap162abd32015-12-10 02:39:40 -0800363 If the participant has not yet sent an RTCP packet (the variable
364 initial is true), the constant Tmin is set to 2.5 seconds, else it
365 is set to 5 seconds.
niklase@google.com470e71d2011-07-07 08:21:25 +0000366
danilchap162abd32015-12-10 02:39:40 -0800367 The interval between RTCP packets is varied randomly over the
368 range [0.5,1.5] times the calculated interval to avoid unintended
369 synchronization of all participants
niklase@google.com470e71d2011-07-07 08:21:25 +0000370
danilchap162abd32015-12-10 02:39:40 -0800371 if we send
372 If the participant is a sender (we_sent true), the constant C is
373 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
374 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
375 number of senders.
niklase@google.com470e71d2011-07-07 08:21:25 +0000376
danilchap162abd32015-12-10 02:39:40 -0800377 if we receive only
378 If we_sent is not true, the constant C is set
379 to the average RTCP packet size divided by 75% of the RTCP
380 bandwidth. The constant n is set to the number of receivers
381 (members - senders). If the number of senders is greater than
382 25%, senders and receivers are treated together.
niklase@google.com470e71d2011-07-07 08:21:25 +0000383
danilchap162abd32015-12-10 02:39:40 -0800384 reconsideration NOT required for peer-to-peer
385 "timer reconsideration" is
386 employed. This algorithm implements a simple back-off mechanism
387 which causes users to hold back RTCP packet transmission if the
388 group sizes are increasing.
niklase@google.com470e71d2011-07-07 08:21:25 +0000389
danilchap162abd32015-12-10 02:39:40 -0800390 n = number of members
391 C = avg_size/(rtcpBW/4)
niklase@google.com470e71d2011-07-07 08:21:25 +0000392
danilchap162abd32015-12-10 02:39:40 -0800393 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
niklase@google.com470e71d2011-07-07 08:21:25 +0000394
danilchap162abd32015-12-10 02:39:40 -0800395 4. The calculated interval T is set to a number uniformly distributed
396 between 0.5 and 1.5 times the deterministic calculated interval.
niklase@google.com470e71d2011-07-07 08:21:25 +0000397
danilchap162abd32015-12-10 02:39:40 -0800398 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
399 for the fact that the timer reconsideration algorithm converges to
400 a value of the RTCP bandwidth below the intended average
401 */
niklase@google.com470e71d2011-07-07 08:21:25 +0000402
Erik Språng242e22b2015-05-11 10:17:43 +0200403 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000404
Erik Språng242e22b2015-05-11 10:17:43 +0200405 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
xians@webrtc.org8738d272011-11-25 13:43:53 +0000406
pbosda903ea2015-10-02 02:36:56 -0700407 if (method_ == RtcpMode::kOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000408 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000409
Erik Språng242e22b2015-05-11 10:17:43 +0200410 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200411 // for video key-frames we want to send the RTCP before the large key-frame
412 // if we have a 100 ms margin
413 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
414 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000415
Erik Språng242e22b2015-05-11 10:17:43 +0200416 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200417 return true;
418 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200419 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200420 // wrap
421 return true;
422 }
423 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000424}
425
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000426int64_t RTCPSender::SendTimeOfSendReport(uint32_t sendReport) {
Erik Språng242e22b2015-05-11 10:17:43 +0200427 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000428
Erik Språng61be2a42015-04-27 13:32:52 +0200429 // This is only saved when we are the sender
Erik Språng242e22b2015-05-11 10:17:43 +0200430 if ((last_send_report_[0] == 0) || (sendReport == 0)) {
Erik Språng61be2a42015-04-27 13:32:52 +0200431 return 0; // will be ignored
432 } else {
433 for (int i = 0; i < RTCP_NUMBER_OF_SR; ++i) {
Erik Språng242e22b2015-05-11 10:17:43 +0200434 if (last_send_report_[i] == sendReport)
435 return last_rtcp_time_[i];
niklase@google.com470e71d2011-07-07 08:21:25 +0000436 }
Erik Språng61be2a42015-04-27 13:32:52 +0200437 }
438 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000439}
440
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000441bool RTCPSender::SendTimeOfXrRrReport(uint32_t mid_ntp,
442 int64_t* time_ms) const {
Erik Språng242e22b2015-05-11 10:17:43 +0200443 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000444
445 if (last_xr_rr_.empty()) {
446 return false;
447 }
448 std::map<uint32_t, int64_t>::const_iterator it = last_xr_rr_.find(mid_ntp);
449 if (it == last_xr_rr_.end()) {
450 return false;
451 }
452 *time_ms = it->second;
453 return true;
454}
455
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200456int32_t RTCPSender::AddReportBlock(const RTCPReportBlock& report_block) {
457 if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000458 LOG(LS_WARNING) << "Too many report blocks.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000459 return -1;
460 }
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200461 rtcp::ReportBlock* block = &report_blocks_[report_block.remoteSSRC];
462 block->To(report_block.remoteSSRC);
463 block->WithFractionLost(report_block.fractionLost);
danilchapdf948f02015-11-13 03:03:13 -0800464 if (!block->WithCumulativeLost(report_block.cumulativeLost)) {
465 LOG(LS_WARNING) << "Cumulative lost is oversized.";
466 return -1;
467 }
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200468 block->WithExtHighestSeqNum(report_block.extendedHighSeqNum);
469 block->WithJitter(report_block.jitter);
470 block->WithLastSr(report_block.lastSR);
471 block->WithDelayLastSr(report_block.delaySinceLastSR);
472
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000473 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000474}
475
Erik Språngf7c57762015-12-04 10:40:35 +0100476rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildSR(const RtcpContext& ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200477 for (int i = (RTCP_NUMBER_OF_SR - 2); i >= 0; i--) {
478 // shift old
Erik Språng242e22b2015-05-11 10:17:43 +0200479 last_send_report_[i + 1] = last_send_report_[i];
480 last_rtcp_time_[i + 1] = last_rtcp_time_[i];
Erik Språng61be2a42015-04-27 13:32:52 +0200481 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000482
Erik Språngf7c57762015-12-04 10:40:35 +0100483 last_rtcp_time_[0] = Clock::NtpToMs(ctx.ntp_sec_, ctx.ntp_frac_);
484 last_send_report_[0] = (ctx.ntp_sec_ << 16) + (ctx.ntp_frac_ >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000485
Erik Språng61be2a42015-04-27 13:32:52 +0200486 // The timestamp of this RTCP packet should be estimated as the timestamp of
487 // the frame being captured at this moment. We are calculating that
488 // timestamp as the last frame's timestamp + the time since the last frame
489 // was captured.
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200490 uint32_t rtp_timestamp =
491 start_timestamp_ + last_rtp_timestamp_ +
492 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) *
Erik Språngf7c57762015-12-04 10:40:35 +0100493 (ctx.feedback_state_.frequency_hz / 1000);
niklase@google.com470e71d2011-07-07 08:21:25 +0000494
Erik Språngf7c57762015-12-04 10:40:35 +0100495 rtcp::SenderReport* report = new rtcp::SenderReport();
496 report->From(ssrc_);
497 report->WithNtpSec(ctx.ntp_sec_);
498 report->WithNtpFrac(ctx.ntp_frac_);
499 report->WithRtpTimestamp(rtp_timestamp);
500 report->WithPacketCount(ctx.feedback_state_.packets_sent);
501 report->WithOctetCount(ctx.feedback_state_.media_bytes_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000502
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200503 for (auto it : report_blocks_)
Erik Språngf7c57762015-12-04 10:40:35 +0100504 report->WithReportBlock(it.second);
niklase@google.com470e71d2011-07-07 08:21:25 +0000505
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200506 report_blocks_.clear();
Erik Språngf7c57762015-12-04 10:40:35 +0100507
508 return rtc::scoped_ptr<rtcp::SenderReport>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000509}
510
Erik Språngf7c57762015-12-04 10:40:35 +0100511rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildSDES(
512 const RtcpContext& ctx) {
Erik Språng0ea42d32015-06-25 14:46:16 +0200513 size_t length_cname = cname_.length();
henrikg91d6ede2015-09-17 00:24:34 -0700514 RTC_CHECK_LT(length_cname, static_cast<size_t>(RTCP_CNAME_SIZE));
niklase@google.com470e71d2011-07-07 08:21:25 +0000515
Erik Språngf7c57762015-12-04 10:40:35 +0100516 rtcp::Sdes* sdes = new rtcp::Sdes();
517 sdes->WithCName(ssrc_, cname_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200518
519 for (const auto it : csrc_cnames_)
Erik Språngf7c57762015-12-04 10:40:35 +0100520 sdes->WithCName(it.first, it.second);
Erik Språng0ea42d32015-06-25 14:46:16 +0200521
Erik Språngf7c57762015-12-04 10:40:35 +0100522 return rtc::scoped_ptr<rtcp::Sdes>(sdes);
niklase@google.com470e71d2011-07-07 08:21:25 +0000523}
524
Erik Språngf7c57762015-12-04 10:40:35 +0100525rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildRR(const RtcpContext& ctx) {
526 rtcp::ReceiverReport* report = new rtcp::ReceiverReport();
527 report->From(ssrc_);
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200528 for (auto it : report_blocks_)
Erik Språngf7c57762015-12-04 10:40:35 +0100529 report->WithReportBlock(it.second);
Erik Språng61be2a42015-04-27 13:32:52 +0200530
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200531 report_blocks_.clear();
Erik Språngf7c57762015-12-04 10:40:35 +0100532 return rtc::scoped_ptr<rtcp::ReceiverReport>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000533}
534
Erik Språngf7c57762015-12-04 10:40:35 +0100535rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildPLI(const RtcpContext& ctx) {
536 rtcp::Pli* pli = new rtcp::Pli();
537 pli->From(ssrc_);
538 pli->To(remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200539
Erik Språng242e22b2015-05-11 10:17:43 +0200540 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
541 "RTCPSender::PLI");
542 ++packet_type_counter_.pli_packets;
543 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
544 ssrc_, packet_type_counter_.pli_packets);
545
Erik Språngf7c57762015-12-04 10:40:35 +0100546 return rtc::scoped_ptr<rtcp::Pli>(pli);
Erik Språng61be2a42015-04-27 13:32:52 +0200547}
548
Erik Språngf7c57762015-12-04 10:40:35 +0100549rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildFIR(const RtcpContext& ctx) {
550 if (!ctx.repeat_)
sprang62dae192015-08-05 02:35:35 -0700551 ++sequence_number_fir_; // Do not increase if repetition.
niklase@google.com470e71d2011-07-07 08:21:25 +0000552
Erik Språngf7c57762015-12-04 10:40:35 +0100553 rtcp::Fir* fir = new rtcp::Fir();
554 fir->From(ssrc_);
555 fir->To(remote_ssrc_);
556 fir->WithCommandSeqNum(sequence_number_fir_);
Erik Språng242e22b2015-05-11 10:17:43 +0200557
558 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
559 "RTCPSender::FIR");
560 ++packet_type_counter_.fir_packets;
561 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
562 ssrc_, packet_type_counter_.fir_packets);
563
Erik Språngf7c57762015-12-04 10:40:35 +0100564 return rtc::scoped_ptr<rtcp::Fir>(fir);
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 | First | Number | PictureID |
572 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
573*/
Erik Språngf7c57762015-12-04 10:40:35 +0100574rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildSLI(const RtcpContext& ctx) {
575 rtcp::Sli* sli = new rtcp::Sli();
576 sli->From(ssrc_);
577 sli->To(remote_ssrc_);
sprang0365a272015-08-11 01:02:37 -0700578 // Crop picture id to 6 least significant bits.
Erik Språngf7c57762015-12-04 10:40:35 +0100579 sli->WithPictureId(ctx.picture_id_ & 0x3F);
580 sli->WithFirstMb(0);
581 sli->WithNumberOfMb(0x1FFF); // 13 bits, only ones for now.
sprang0365a272015-08-11 01:02:37 -0700582
Erik Språngf7c57762015-12-04 10:40:35 +0100583 return rtc::scoped_ptr<rtcp::Sli>(sli);
niklase@google.com470e71d2011-07-07 08:21:25 +0000584}
585
586/*
587 0 1 2 3
588 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
589 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
590 | PB |0| Payload Type| Native RPSI bit string |
591 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
592 | defined per codec ... | Padding (0) |
593 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
594*/
595/*
596* Note: not generic made for VP8
597*/
Erik Språngf7c57762015-12-04 10:40:35 +0100598rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildRPSI(
599 const RtcpContext& ctx) {
600 if (ctx.feedback_state_.send_payload_type == 0xFF)
601 return nullptr;
Erik Språng242e22b2015-05-11 10:17:43 +0200602
Erik Språngf7c57762015-12-04 10:40:35 +0100603 rtcp::Rpsi* rpsi = new rtcp::Rpsi();
604 rpsi->From(ssrc_);
605 rpsi->To(remote_ssrc_);
606 rpsi->WithPayloadType(ctx.feedback_state_.send_payload_type);
607 rpsi->WithPictureId(ctx.picture_id_);
sprangcf7f54d2015-08-13 04:37:42 -0700608
Erik Språngf7c57762015-12-04 10:40:35 +0100609 return rtc::scoped_ptr<rtcp::Rpsi>(rpsi);
niklase@google.com470e71d2011-07-07 08:21:25 +0000610}
611
Erik Språngf7c57762015-12-04 10:40:35 +0100612rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildREMB(
613 const RtcpContext& ctx) {
614 rtcp::Remb* remb = new rtcp::Remb();
615 remb->From(ssrc_);
sprangdd4edc52015-08-21 04:21:51 -0700616 for (uint32_t ssrc : remb_ssrcs_)
Erik Språngf7c57762015-12-04 10:40:35 +0100617 remb->AppliesTo(ssrc);
618 remb->WithBitrateBps(remb_bitrate_);
Erik Språng61be2a42015-04-27 13:32:52 +0200619
Erik Språng242e22b2015-05-11 10:17:43 +0200620 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
621 "RTCPSender::REMB");
622
Erik Språngf7c57762015-12-04 10:40:35 +0100623 return rtc::scoped_ptr<rtcp::Remb>(remb);
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000624}
625
Erik Språng61be2a42015-04-27 13:32:52 +0200626void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
Erik Språng242e22b2015-05-11 10:17:43 +0200627 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
628 tmmbr_send_ = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000629}
630
Erik Språngf7c57762015-12-04 10:40:35 +0100631rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBR(
632 const RtcpContext& ctx) {
633 if (ctx.feedback_state_.module == nullptr)
634 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200635 // Before sending the TMMBR check the received TMMBN, only an owner is
636 // allowed to raise the bitrate:
637 // * If the sender is an owner of the TMMBN -> send TMMBR
638 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000639
Erik Språng61be2a42015-04-27 13:32:52 +0200640 // get current bounding set from RTCP receiver
641 bool tmmbrOwner = false;
642 // store in candidateSet, allocates one extra slot
Erik Språng242e22b2015-05-11 10:17:43 +0200643 TMMBRSet* candidateSet = tmmbr_help_.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000644
Erik Språng242e22b2015-05-11 10:17:43 +0200645 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
646 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
Erik Språng61be2a42015-04-27 13:32:52 +0200647 // since RTCPreceiver is not doing the reverse we should be fine
648 int32_t lengthOfBoundingSet =
danilchap6db6cdc2015-12-15 02:54:47 -0800649 ctx.feedback_state_.module->BoundingSet(&tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +0000650
Erik Språng61be2a42015-04-27 13:32:52 +0200651 if (lengthOfBoundingSet > 0) {
652 for (int32_t i = 0; i < lengthOfBoundingSet; i++) {
Erik Språng242e22b2015-05-11 10:17:43 +0200653 if (candidateSet->Tmmbr(i) == tmmbr_send_ &&
654 candidateSet->PacketOH(i) == packet_oh_send_) {
Erik Språngf7c57762015-12-04 10:40:35 +0100655 // Do not send the same tuple.
656 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200657 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000658 }
Erik Språng61be2a42015-04-27 13:32:52 +0200659 if (!tmmbrOwner) {
660 // use received bounding set as candidate set
661 // add current tuple
Erik Språng242e22b2015-05-11 10:17:43 +0200662 candidateSet->SetEntry(lengthOfBoundingSet, tmmbr_send_, packet_oh_send_,
663 ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200664 int numCandidates = lengthOfBoundingSet + 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000665
Erik Språng61be2a42015-04-27 13:32:52 +0200666 // find bounding set
Erik Språngf7c57762015-12-04 10:40:35 +0100667 TMMBRSet* boundingSet = nullptr;
Erik Språng242e22b2015-05-11 10:17:43 +0200668 int numBoundingSet = tmmbr_help_.FindTMMBRBoundingSet(boundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200669 if (numBoundingSet > 0 || numBoundingSet <= numCandidates)
Erik Språng242e22b2015-05-11 10:17:43 +0200670 tmmbrOwner = tmmbr_help_.IsOwner(ssrc_, numBoundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200671 if (!tmmbrOwner) {
Erik Språngf7c57762015-12-04 10:40:35 +0100672 // Did not enter bounding set, no meaning to send this request.
673 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200674 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000675 }
Erik Språng61be2a42015-04-27 13:32:52 +0200676 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000677
Erik Språngf7c57762015-12-04 10:40:35 +0100678 if (!tmmbr_send_)
679 return nullptr;
sprang81a3e602015-08-21 05:30:11 -0700680
Erik Språngf7c57762015-12-04 10:40:35 +0100681 rtcp::Tmmbr* tmmbr = new rtcp::Tmmbr();
682 tmmbr->From(ssrc_);
683 tmmbr->To(remote_ssrc_);
684 tmmbr->WithBitrateKbps(tmmbr_send_);
685 tmmbr->WithOverhead(packet_oh_send_);
686
687 return rtc::scoped_ptr<rtcp::Tmmbr>(tmmbr);
Erik Språng61be2a42015-04-27 13:32:52 +0200688}
689
Erik Språngf7c57762015-12-04 10:40:35 +0100690rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBN(
691 const RtcpContext& ctx) {
Erik Språng242e22b2015-05-11 10:17:43 +0200692 TMMBRSet* boundingSet = tmmbr_help_.BoundingSetToSend();
Erik Språngf7c57762015-12-04 10:40:35 +0100693 if (boundingSet == nullptr)
694 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200695
Erik Språngf7c57762015-12-04 10:40:35 +0100696 rtcp::Tmmbn* tmmbn = new rtcp::Tmmbn();
697 tmmbn->From(ssrc_);
sprangd83df502015-08-27 01:05:08 -0700698 for (uint32_t i = 0; i < boundingSet->lengthOfSet(); i++) {
699 if (boundingSet->Tmmbr(i) > 0) {
Erik Språngf7c57762015-12-04 10:40:35 +0100700 tmmbn->WithTmmbr(boundingSet->Ssrc(i), boundingSet->Tmmbr(i),
701 boundingSet->PacketOH(i));
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000702 }
Erik Språng61be2a42015-04-27 13:32:52 +0200703 }
sprangd83df502015-08-27 01:05:08 -0700704
Erik Språngf7c57762015-12-04 10:40:35 +0100705 return rtc::scoped_ptr<rtcp::Tmmbn>(tmmbn);
niklase@google.com470e71d2011-07-07 08:21:25 +0000706}
707
Erik Språngf7c57762015-12-04 10:40:35 +0100708rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildAPP(const RtcpContext& ctx) {
709 rtcp::App* app = new rtcp::App();
710 app->From(ssrc_);
711 app->WithSubType(app_sub_type_);
712 app->WithName(app_name_);
713 app->WithData(app_data_.get(), app_length_);
Erik Språng521875a2015-09-01 10:11:16 +0200714
Erik Språngf7c57762015-12-04 10:40:35 +0100715 return rtc::scoped_ptr<rtcp::App>(app);
Erik Språng61be2a42015-04-27 13:32:52 +0200716}
717
Erik Språngf7c57762015-12-04 10:40:35 +0100718rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildNACK(
719 const RtcpContext& ctx) {
720 rtcp::Nack* nack = new rtcp::Nack();
721 nack->From(ssrc_);
722 nack->To(remote_ssrc_);
723 nack->WithList(ctx.nack_list_, ctx.nack_size_);
Erik Språng61be2a42015-04-27 13:32:52 +0200724
725 // Report stats.
726 NACKStringBuilder stringBuilder;
Erik Språngf7c57762015-12-04 10:40:35 +0100727 for (int idx = 0; idx < ctx.nack_size_; ++idx) {
728 stringBuilder.PushNACK(ctx.nack_list_[idx]);
729 nack_stats_.ReportRequest(ctx.nack_list_[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +0200730 }
Erik Språng61be2a42015-04-27 13:32:52 +0200731 packet_type_counter_.nack_requests = nack_stats_.requests();
732 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +0200733
734 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
735 "RTCPSender::NACK", "nacks",
736 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
737 ++packet_type_counter_.nack_packets;
738 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
739 ssrc_, packet_type_counter_.nack_packets);
740
Erik Språngf7c57762015-12-04 10:40:35 +0100741 return rtc::scoped_ptr<rtcp::Nack>(nack);
Erik Språng61be2a42015-04-27 13:32:52 +0200742}
743
Erik Språngf7c57762015-12-04 10:40:35 +0100744rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildBYE(const RtcpContext& ctx) {
745 rtcp::Bye* bye = new rtcp::Bye();
746 bye->From(ssrc_);
sprangd8ee4f92015-08-24 03:25:19 -0700747 for (uint32_t csrc : csrcs_)
Erik Språngf7c57762015-12-04 10:40:35 +0100748 bye->WithCsrc(csrc);
sprangd8ee4f92015-08-24 03:25:19 -0700749
Erik Språngf7c57762015-12-04 10:40:35 +0100750 return rtc::scoped_ptr<rtcp::Bye>(bye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000751}
752
Erik Språngf7c57762015-12-04 10:40:35 +0100753rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildReceiverReferenceTime(
754 const RtcpContext& ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200755 if (last_xr_rr_.size() >= RTCP_NUMBER_OF_SR)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000756 last_xr_rr_.erase(last_xr_rr_.begin());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000757 last_xr_rr_.insert(std::pair<uint32_t, int64_t>(
Erik Språngf7c57762015-12-04 10:40:35 +0100758 RTCPUtility::MidNtp(ctx.ntp_sec_, ctx.ntp_frac_),
759 Clock::NtpToMs(ctx.ntp_sec_, ctx.ntp_frac_)));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000760
Erik Språngf7c57762015-12-04 10:40:35 +0100761 rtcp::Xr* xr = new rtcp::Xr();
762 xr->From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000763
Erik Språngca28fdc2015-08-31 14:00:50 +0200764 rtcp::Rrtr rrtr;
Danil Chapovalovfc47ed62015-12-07 14:46:35 +0100765 rrtr.WithNtp(NtpTime(ctx.ntp_sec_, ctx.ntp_frac_));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000766
Erik Språngf7c57762015-12-04 10:40:35 +0100767 xr->WithRrtr(&rrtr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000768
Erik Språngca28fdc2015-08-31 14:00:50 +0200769 // TODO(sprang): Merge XR report sending to contain all of RRTR, DLRR, VOIP?
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000770
Erik Språngf7c57762015-12-04 10:40:35 +0100771 return rtc::scoped_ptr<rtcp::Xr>(xr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000772}
773
Erik Språngf7c57762015-12-04 10:40:35 +0100774rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildDlrr(
775 const RtcpContext& ctx) {
776 rtcp::Xr* xr = new rtcp::Xr();
777 xr->From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000778
Erik Språngca28fdc2015-08-31 14:00:50 +0200779 rtcp::Dlrr dlrr;
Erik Språngf7c57762015-12-04 10:40:35 +0100780 const RtcpReceiveTimeInfo& info = ctx.feedback_state_.last_xr_rr;
Erik Språngca28fdc2015-08-31 14:00:50 +0200781 dlrr.WithDlrrItem(info.sourceSSRC, info.lastRR, info.delaySinceLastRR);
782
Erik Språngf7c57762015-12-04 10:40:35 +0100783 xr->WithDlrr(&dlrr);
Erik Språngca28fdc2015-08-31 14:00:50 +0200784
Erik Språngf7c57762015-12-04 10:40:35 +0100785 return rtc::scoped_ptr<rtcp::Xr>(xr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000786}
787
Erik Språng242e22b2015-05-11 10:17:43 +0200788// TODO(sprang): Add a unit test for this, or remove if the code isn't used.
Erik Språngf7c57762015-12-04 10:40:35 +0100789rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildVoIPMetric(
790 const RtcpContext& context) {
791 rtcp::Xr* xr = new rtcp::Xr();
792 xr->From(ssrc_);
Erik Språngca28fdc2015-08-31 14:00:50 +0200793
794 rtcp::VoipMetric voip;
795 voip.To(remote_ssrc_);
danilchap91941ae2015-12-15 07:06:36 -0800796 voip.WithVoipMetric(xr_voip_metric_);
Erik Språngca28fdc2015-08-31 14:00:50 +0200797
Erik Språngf7c57762015-12-04 10:40:35 +0100798 xr->WithVoipMetric(&voip);
Erik Språngca28fdc2015-08-31 14:00:50 +0200799
Erik Språngf7c57762015-12-04 10:40:35 +0100800 return rtc::scoped_ptr<rtcp::Xr>(xr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000801}
802
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000803int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200804 RTCPPacketType packetType,
805 int32_t nack_size,
806 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000807 bool repeat,
808 uint64_t pictureID) {
Erik Språng242e22b2015-05-11 10:17:43 +0200809 return SendCompoundRTCP(
810 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
811 nack_size, nack_list, repeat, pictureID);
812}
813
814int32_t RTCPSender::SendCompoundRTCP(
815 const FeedbackState& feedback_state,
Erik Språngf7c57762015-12-04 10:40:35 +0100816 const std::set<RTCPPacketType>& packet_types,
Erik Språng242e22b2015-05-11 10:17:43 +0200817 int32_t nack_size,
818 const uint16_t* nack_list,
819 bool repeat,
820 uint64_t pictureID) {
Erik Språngf7c57762015-12-04 10:40:35 +0100821 PacketContainer container(transport_);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000822 {
Erik Språng242e22b2015-05-11 10:17:43 +0200823 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
pbosda903ea2015-10-02 02:36:56 -0700824 if (method_ == RtcpMode::kOff) {
Erik Språng61be2a42015-04-27 13:32:52 +0200825 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
826 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +0000827 }
Erik Språngf7c57762015-12-04 10:40:35 +0100828
829 // We need to send our NTP even if we haven't received any reports.
830 uint32_t ntp_sec;
831 uint32_t ntp_frac;
832 clock_->CurrentNtp(ntp_sec, ntp_frac);
833 RtcpContext context(feedback_state, nack_size, nack_list, repeat, pictureID,
834 ntp_sec, ntp_frac, &container);
835
836 PrepareReport(packet_types, feedback_state);
837
838 auto it = report_flags_.begin();
839 while (it != report_flags_.end()) {
840 auto builder_it = builders_.find(it->type);
841 RTC_DCHECK(builder_it != builders_.end());
842 if (it->is_volatile) {
843 report_flags_.erase(it++);
844 } else {
845 ++it;
846 }
847
848 BuilderFunc func = builder_it->second;
849 rtc::scoped_ptr<rtcp::RtcpPacket> packet = (this->*func)(context);
850 if (packet.get() == nullptr)
851 return -1;
852 container.Append(packet.release());
853 }
854
855 if (packet_type_counter_observer_ != nullptr) {
856 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
857 remote_ssrc_, packet_type_counter_);
858 }
859
860 RTC_DCHECK(AllVolatileFlagsConsumed());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000861 }
Erik Språng61be2a42015-04-27 13:32:52 +0200862
Erik Språngf7c57762015-12-04 10:40:35 +0100863 size_t bytes_sent = container.SendPackets();
864 return bytes_sent == 0 ? -1 : 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000865}
866
Erik Språngf7c57762015-12-04 10:40:35 +0100867void RTCPSender::PrepareReport(const std::set<RTCPPacketType>& packetTypes,
868 const FeedbackState& feedback_state) {
Erik Språng242e22b2015-05-11 10:17:43 +0200869 // Add all flags as volatile. Non volatile entries will not be overwritten
870 // and all new volatile flags added will be consumed by the end of this call.
871 SetFlags(packetTypes, true);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000872
Erik Språng61be2a42015-04-27 13:32:52 +0200873 if (packet_type_counter_.first_packet_time_ms == -1)
Erik Språng242e22b2015-05-11 10:17:43 +0200874 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språng61be2a42015-04-27 13:32:52 +0200875
Erik Språng242e22b2015-05-11 10:17:43 +0200876 bool generate_report;
877 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
878 // Report type already explicitly set, don't automatically populate.
879 generate_report = true;
henrikg91d6ede2015-09-17 00:24:34 -0700880 RTC_DCHECK(ConsumeFlag(kRtcpReport) == false);
Erik Språng242e22b2015-05-11 10:17:43 +0200881 } else {
882 generate_report =
pbosda903ea2015-10-02 02:36:56 -0700883 (ConsumeFlag(kRtcpReport) && method_ == RtcpMode::kReducedSize) ||
884 method_ == RtcpMode::kCompound;
Erik Språng242e22b2015-05-11 10:17:43 +0200885 if (generate_report)
886 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000887 }
888
Erik Språng0ea42d32015-06-25 14:46:16 +0200889 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
Erik Språng242e22b2015-05-11 10:17:43 +0200890 SetFlag(kRtcpSdes, true);
891
Erik Språng242e22b2015-05-11 10:17:43 +0200892 if (generate_report) {
893 if (!sending_ && xr_send_receiver_reference_time_enabled_)
894 SetFlag(kRtcpXrReceiverReferenceTime, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200895 if (feedback_state.has_last_xr_rr)
Erik Språng242e22b2015-05-11 10:17:43 +0200896 SetFlag(kRtcpXrDlrrReportBlock, true);
897
898 // generate next time to send an RTCP report
danilchap47a740b2015-12-15 00:30:07 -0800899 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000900
danilchap47a740b2015-12-15 00:30:07 -0800901 if (!audio_) {
Erik Språng242e22b2015-05-11 10:17:43 +0200902 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200903 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
904 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
905 if (send_bitrate_kbit != 0)
906 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000907 }
Erik Språng61be2a42015-04-27 13:32:52 +0200908 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
909 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
Erik Språng61be2a42015-04-27 13:32:52 +0200910 }
danilchap47a740b2015-12-15 00:30:07 -0800911 // The interval between RTCP packets is varied randomly over the
912 // range [1/2,3/2] times the calculated interval.
913 uint32_t timeToNext =
914 random_.Rand(minIntervalMs * 1 / 2, minIntervalMs * 3 / 2);
Erik Språng242e22b2015-05-11 10:17:43 +0200915 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000916
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000917 StatisticianMap statisticians =
918 receive_statistics_->GetActiveStatisticians();
919 if (!statisticians.empty()) {
Erik Språng61be2a42015-04-27 13:32:52 +0200920 for (auto it = statisticians.begin(); it != statisticians.end(); ++it) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000921 RTCPReportBlock report_block;
Erik Språngf7c57762015-12-04 10:40:35 +0100922 if (PrepareReportBlock(feedback_state, it->first, it->second,
923 &report_block)) {
danilchapdf948f02015-11-13 03:03:13 -0800924 // TODO(danilchap) AddReportBlock may fail (for 2 different reasons).
925 // Probably it shouldn't be ignored.
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200926 AddReportBlock(report_block);
Erik Språng61be2a42015-04-27 13:32:52 +0200927 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000928 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000929 }
930 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000931}
932
Erik Språngf7c57762015-12-04 10:40:35 +0100933bool RTCPSender::PrepareReportBlock(const FeedbackState& feedback_state,
934 uint32_t ssrc,
935 StreamStatistician* statistician,
936 RTCPReportBlock* report_block) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000937 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000938 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000939 if (!statistician->GetStatistics(&stats, true))
940 return false;
941 report_block->fractionLost = stats.fraction_lost;
942 report_block->cumulativeLost = stats.cumulative_lost;
danilchap162abd32015-12-10 02:39:40 -0800943 report_block->extendedHighSeqNum = stats.extended_max_sequence_number;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000944 report_block->jitter = stats.jitter;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200945 report_block->remoteSSRC = ssrc;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000946
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200947 // TODO(sprang): Do we really need separate time stamps for each report?
948 // Get our NTP as late as possible to avoid a race.
949 uint32_t ntp_secs;
950 uint32_t ntp_frac;
951 clock_->CurrentNtp(ntp_secs, ntp_frac);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000952
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200953 // Delay since last received report.
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000954 uint32_t delaySinceLastReceivedSR = 0;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000955 if ((feedback_state.last_rr_ntp_secs != 0) ||
956 (feedback_state.last_rr_ntp_frac != 0)) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200957 // Get the 16 lowest bits of seconds and the 16 highest bits of fractions.
958 uint32_t now = ntp_secs & 0x0000FFFF;
Erik Språng61be2a42015-04-27 13:32:52 +0200959 now <<= 16;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200960 now += (ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000961
Erik Språng61be2a42015-04-27 13:32:52 +0200962 uint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
963 receiveTime <<= 16;
964 receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000965
danilchap162abd32015-12-10 02:39:40 -0800966 delaySinceLastReceivedSR = now - receiveTime;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000967 }
968 report_block->delaySinceLastSR = delaySinceLastReceivedSR;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000969 report_block->lastSR = feedback_state.remote_sr;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000970 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000971}
972
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000973void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
974 assert(csrcs.size() <= kRtpCsrcSize);
Erik Språng242e22b2015-05-11 10:17:43 +0200975 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000976 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +0000977}
978
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000979int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
980 uint32_t name,
981 const uint8_t* data,
982 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +0200983 if (length % 4 != 0) {
984 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
985 return -1;
986 }
Erik Språng242e22b2015-05-11 10:17:43 +0200987 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000988
Erik Språng242e22b2015-05-11 10:17:43 +0200989 SetFlag(kRtcpApp, true);
990 app_sub_type_ = subType;
991 app_name_ = name;
992 app_data_.reset(new uint8_t[length]);
993 app_length_ = length;
994 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +0200995 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000996}
997
Erik Språng61be2a42015-04-27 13:32:52 +0200998int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
Erik Språng242e22b2015-05-11 10:17:43 +0200999 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1000 memcpy(&xr_voip_metric_, VoIPMetric, sizeof(RTCPVoIPMetric));
niklase@google.com470e71d2011-07-07 08:21:25 +00001001
Erik Språng242e22b2015-05-11 10:17:43 +02001002 SetFlag(kRtcpXrVoipMetric, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001003 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001004}
1005
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001006void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +02001007 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1008 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001009}
1010
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00001011bool RTCPSender::RtcpXrReceiverReferenceTime() const {
Erik Språng242e22b2015-05-11 10:17:43 +02001012 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1013 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00001014}
1015
niklase@google.com470e71d2011-07-07 08:21:25 +00001016// no callbacks allowed inside this function
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001017int32_t RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
1018 uint32_t maxBitrateKbit) {
Erik Språng242e22b2015-05-11 10:17:43 +02001019 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +00001020
Erik Språng242e22b2015-05-11 10:17:43 +02001021 if (0 == tmmbr_help_.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit)) {
1022 SetFlag(kRtcpTmmbn, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001023 return 0;
1024 }
1025 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001026}
Erik Språng61be2a42015-04-27 13:32:52 +02001027
Erik Språng242e22b2015-05-11 10:17:43 +02001028void RTCPSender::SetFlag(RTCPPacketType type, bool is_volatile) {
1029 report_flags_.insert(ReportFlag(type, is_volatile));
1030}
1031
1032void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
1033 bool is_volatile) {
1034 for (RTCPPacketType type : types)
1035 SetFlag(type, is_volatile);
1036}
1037
1038bool RTCPSender::IsFlagPresent(RTCPPacketType type) const {
1039 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
1040}
1041
1042bool RTCPSender::ConsumeFlag(RTCPPacketType type, bool forced) {
1043 auto it = report_flags_.find(ReportFlag(type, false));
1044 if (it == report_flags_.end())
1045 return false;
1046 if (it->is_volatile || forced)
1047 report_flags_.erase((it));
1048 return true;
1049}
1050
1051bool RTCPSender::AllVolatileFlagsConsumed() const {
1052 for (const ReportFlag& flag : report_flags_) {
1053 if (flag.is_volatile)
1054 return false;
1055 }
1056 return true;
1057}
1058
sprang233bd872015-09-08 13:25:16 -07001059bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
sprang233bd872015-09-08 13:25:16 -07001060 class Sender : public rtcp::RtcpPacket::PacketReadyCallback {
1061 public:
danilchap6db6cdc2015-12-15 02:54:47 -08001062 explicit Sender(Transport* transport)
Peter Boströmac547a62015-09-17 23:03:57 +02001063 : transport_(transport), send_failure_(false) {}
sprang233bd872015-09-08 13:25:16 -07001064
1065 void OnPacketReady(uint8_t* data, size_t length) override {
pbos2d566682015-09-28 09:59:31 -07001066 if (!transport_->SendRtcp(data, length))
sprang233bd872015-09-08 13:25:16 -07001067 send_failure_ = true;
1068 }
1069
1070 Transport* const transport_;
sprang233bd872015-09-08 13:25:16 -07001071 bool send_failure_;
sprang86fd9ed2015-09-29 04:45:43 -07001072 } sender(transport_);
sprang233bd872015-09-08 13:25:16 -07001073
1074 uint8_t buffer[IP_PACKET_SIZE];
1075 return packet.BuildExternalBuffer(buffer, IP_PACKET_SIZE, &sender) &&
1076 !sender.send_failure_;
1077}
1078
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001079} // namespace webrtc