blob: 5add7cf3490cd64c7ed5a971fc7dfcf1b1e1dc82 [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
14#include <stdlib.h> // rand
stefan@webrtc.org9354cc92012-06-07 08:10:14 +000015#include <string.h> // memcpy
niklase@google.com470e71d2011-07-07 08:21:25 +000016
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000017#include <algorithm> // min
Erik Språng61be2a42015-04-27 13:32:52 +020018#include <limits> // max
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"
danilchapf8385ad2015-11-27 05:36:09 -080027#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/pli.h"
sprang233bd872015-09-08 13:25:16 -070028#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
tommie4f96502015-10-20 23:00:48 -070029#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010030#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000031
niklase@google.com470e71d2011-07-07 08:21:25 +000032namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000033
34using RTCPUtility::RTCPCnameInformation;
35
Erik Språng61be2a42015-04-27 13:32:52 +020036NACKStringBuilder::NACKStringBuilder()
Erik Språng242e22b2015-05-11 10:17:43 +020037 : stream_(""), count_(0), prevNack_(0), consecutive_(false) {
edjee@google.com79b02892013-04-04 19:43:34 +000038}
39
pbos@webrtc.orgf3e4cee2013-07-31 15:17:19 +000040NACKStringBuilder::~NACKStringBuilder() {}
41
pbos@webrtc.org2f446732013-04-08 11:08:41 +000042void NACKStringBuilder::PushNACK(uint16_t nack)
edjee@google.com79b02892013-04-04 19:43:34 +000043{
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),
77 module(nullptr) {
78}
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000079
Erik Språngf7c57762015-12-04 10:40:35 +010080class PacketContainer : public rtcp::Empty,
81 public rtcp::RtcpPacket::PacketReadyCallback {
82 public:
83 explicit PacketContainer(Transport* transport)
84 : transport_(transport), bytes_sent_(0) {}
85 virtual ~PacketContainer() {
86 for (RtcpPacket* packet : appended_packets_)
87 delete packet;
88 }
89
90 void OnPacketReady(uint8_t* data, size_t length) override {
91 if (transport_->SendRtcp(data, length))
92 bytes_sent_ += length;
93 }
94
95 size_t SendPackets() {
96 rtcp::Empty::Build(this);
97 return bytes_sent_;
98 }
99
100 private:
101 Transport* transport_;
102 size_t bytes_sent_;
103};
104
105class RTCPSender::RtcpContext {
106 public:
Erik Språng242e22b2015-05-11 10:17:43 +0200107 RtcpContext(const FeedbackState& feedback_state,
108 int32_t nack_size,
109 const uint16_t* nack_list,
110 bool repeat,
111 uint64_t picture_id,
Erik Språngf7c57762015-12-04 10:40:35 +0100112 uint32_t ntp_sec,
113 uint32_t ntp_frac,
114 PacketContainer* container)
115 : feedback_state_(feedback_state),
116 nack_size_(nack_size),
117 nack_list_(nack_list),
118 repeat_(repeat),
119 picture_id_(picture_id),
120 ntp_sec_(ntp_sec),
121 ntp_frac_(ntp_frac),
122 container_(container) {}
Erik Språng242e22b2015-05-11 10:17:43 +0200123
Erik Språngf7c57762015-12-04 10:40:35 +0100124 virtual ~RtcpContext() {}
Erik Språng242e22b2015-05-11 10:17:43 +0200125
Erik Språngf7c57762015-12-04 10:40:35 +0100126 const FeedbackState& feedback_state_;
127 const int32_t nack_size_;
128 const uint16_t* nack_list_;
129 const bool repeat_;
130 const uint64_t picture_id_;
131 const uint32_t ntp_sec_;
132 const uint32_t ntp_frac_;
Erik Språng242e22b2015-05-11 10:17:43 +0200133
Erik Språngf7c57762015-12-04 10:40:35 +0100134 PacketContainer* const container_;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200135};
136
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000137RTCPSender::RTCPSender(
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000138 bool audio,
139 Clock* clock,
140 ReceiveStatistics* receive_statistics,
sprang86fd9ed2015-09-29 04:45:43 -0700141 RtcpPacketTypeCounterObserver* packet_type_counter_observer,
142 Transport* outgoing_transport)
Peter Boströmac547a62015-09-17 23:03:57 +0200143 : audio_(audio),
Erik Språng242e22b2015-05-11 10:17:43 +0200144 clock_(clock),
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
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000199RTCPSender::~RTCPSender() {
niklase@google.com470e71d2011-07-07 08:21:25 +0000200}
201
pbosda903ea2015-10-02 02:36:56 -0700202RtcpMode RTCPSender::Status() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200203 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
204 return method_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000205}
206
pbosda903ea2015-10-02 02:36:56 -0700207void RTCPSender::SetRTCPStatus(RtcpMode method) {
Erik Språng242e22b2015-05-11 10:17:43 +0200208 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
209 method_ = method;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000210
pbosda903ea2015-10-02 02:36:56 -0700211 if (method == RtcpMode::kOff)
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000212 return;
Erik Språng242e22b2015-05-11 10:17:43 +0200213 next_time_to_send_rtcp_ =
214 clock_->TimeInMilliseconds() +
215 (audio_ ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000216}
217
Erik Språng61be2a42015-04-27 13:32:52 +0200218bool RTCPSender::Sending() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200219 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
220 return sending_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000221}
222
Erik Språng61be2a42015-04-27 13:32:52 +0200223int32_t RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
224 bool sending) {
225 bool sendRTCPBye = false;
226 {
Erik Språng242e22b2015-05-11 10:17:43 +0200227 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000228
pbosda903ea2015-10-02 02:36:56 -0700229 if (method_ != RtcpMode::kOff) {
Erik Språng242e22b2015-05-11 10:17:43 +0200230 if (sending == false && sending_ == true) {
Erik Språng61be2a42015-04-27 13:32:52 +0200231 // Trigger RTCP bye
232 sendRTCPBye = true;
233 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000234 }
Erik Språng242e22b2015-05-11 10:17:43 +0200235 sending_ = sending;
Erik Språng61be2a42015-04-27 13:32:52 +0200236 }
237 if (sendRTCPBye)
238 return SendRTCP(feedback_state, kRtcpBye);
239 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000240}
241
Erik Språng61be2a42015-04-27 13:32:52 +0200242bool RTCPSender::REMB() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200243 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
244 return remb_enabled_;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000245}
246
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000247void RTCPSender::SetREMBStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200248 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
249 remb_enabled_ = enable;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000250}
251
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000252void RTCPSender::SetREMBData(uint32_t bitrate,
253 const std::vector<uint32_t>& ssrcs) {
Erik Språng242e22b2015-05-11 10:17:43 +0200254 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
255 remb_bitrate_ = bitrate;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000256 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000257
Erik Språng242e22b2015-05-11 10:17:43 +0200258 if (remb_enabled_)
259 SetFlag(kRtcpRemb, false);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000260 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
261 // throttled by the caller.
Erik Språng242e22b2015-05-11 10:17:43 +0200262 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000263}
264
Erik Språng61be2a42015-04-27 13:32:52 +0200265bool RTCPSender::TMMBR() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200266 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
267 return IsFlagPresent(RTCPPacketType::kRtcpTmmbr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000268}
269
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000270void RTCPSender::SetTMMBRStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200271 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
272 if (enable) {
273 SetFlag(RTCPPacketType::kRtcpTmmbr, false);
274 } else {
275 ConsumeFlag(RTCPPacketType::kRtcpTmmbr, true);
276 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000277}
278
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000279void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
Erik Språng242e22b2015-05-11 10:17:43 +0200280 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000281 start_timestamp_ = start_timestamp;
282}
283
284void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
285 int64_t capture_time_ms) {
Erik Språng242e22b2015-05-11 10:17:43 +0200286 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000287 last_rtp_timestamp_ = rtp_timestamp;
288 if (capture_time_ms < 0) {
289 // We don't currently get a capture time from VoiceEngine.
Erik Språng242e22b2015-05-11 10:17:43 +0200290 last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000291 } else {
292 last_frame_capture_time_ms_ = capture_time_ms;
293 }
294}
295
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000296void RTCPSender::SetSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200297 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000298
Erik Språng242e22b2015-05-11 10:17:43 +0200299 if (ssrc_ != 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200300 // not first SetSSRC, probably due to a collision
301 // schedule a new RTCP report
302 // make sure that we send a RTP packet
Erik Språng242e22b2015-05-11 10:17:43 +0200303 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
Erik Språng61be2a42015-04-27 13:32:52 +0200304 }
Erik Språng242e22b2015-05-11 10:17:43 +0200305 ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000306}
307
Erik Språng61be2a42015-04-27 13:32:52 +0200308void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200309 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
310 remote_ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000311}
312
Peter Boström9ba52f82015-06-01 14:12:28 +0200313int32_t RTCPSender::SetCNAME(const char* c_name) {
314 if (!c_name)
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000315 return -1;
316
henrikg91d6ede2015-09-17 00:24:34 -0700317 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
Erik Språng242e22b2015-05-11 10:17:43 +0200318 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200319 cname_ = c_name;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000320 return 0;
321}
322
Erik Språng0ea42d32015-06-25 14:46:16 +0200323int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC, const char* c_name) {
324 assert(c_name);
henrikg91d6ede2015-09-17 00:24:34 -0700325 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
Erik Språng242e22b2015-05-11 10:17:43 +0200326 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200327 if (csrc_cnames_.size() >= kRtpCsrcSize)
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000328 return -1;
Erik Språng0ea42d32015-06-25 14:46:16 +0200329
330 csrc_cnames_[SSRC] = c_name;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000331 return 0;
332}
333
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000334int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
Erik Språng242e22b2015-05-11 10:17:43 +0200335 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200336 auto it = csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000337
Erik Språng242e22b2015-05-11 10:17:43 +0200338 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000339 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200340
Erik Språng242e22b2015-05-11 10:17:43 +0200341 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000342 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000343}
344
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000345bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
niklase@google.com470e71d2011-07-07 08:21:25 +0000346/*
347 For audio we use a fix 5 sec interval
348
349 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000350 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
351 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000352
353
354From RFC 3550
355
356 MAX RTCP BW is 5% if the session BW
357 A send report is approximately 65 bytes inc CNAME
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000358 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000359
360 The RECOMMENDED value for the reduced minimum in seconds is 360
361 divided by the session bandwidth in kilobits/second. This minimum
362 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
363
364 If the participant has not yet sent an RTCP packet (the variable
365 initial is true), the constant Tmin is set to 2.5 seconds, else it
366 is set to 5 seconds.
367
368 The interval between RTCP packets is varied randomly over the
369 range [0.5,1.5] times the calculated interval to avoid unintended
370 synchronization of all participants
371
372 if we send
373 If the participant is a sender (we_sent true), the constant C is
374 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
375 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
376 number of senders.
377
378 if we receive only
379 If we_sent is not true, the constant C is set
380 to the average RTCP packet size divided by 75% of the RTCP
381 bandwidth. The constant n is set to the number of receivers
382 (members - senders). If the number of senders is greater than
383 25%, senders and receivers are treated together.
384
385 reconsideration NOT required for peer-to-peer
386 "timer reconsideration" is
387 employed. This algorithm implements a simple back-off mechanism
388 which causes users to hold back RTCP packet transmission if the
389 group sizes are increasing.
390
391 n = number of members
392 C = avg_size/(rtcpBW/4)
393
394 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
395
396 4. The calculated interval T is set to a number uniformly distributed
397 between 0.5 and 1.5 times the deterministic calculated interval.
398
399 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
400 for the fact that the timer reconsideration algorithm converges to
401 a value of the RTCP bandwidth below the intended average
402*/
403
Erik Språng242e22b2015-05-11 10:17:43 +0200404 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000405
Erik Språng242e22b2015-05-11 10:17:43 +0200406 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
xians@webrtc.org8738d272011-11-25 13:43:53 +0000407
pbosda903ea2015-10-02 02:36:56 -0700408 if (method_ == RtcpMode::kOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000409 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000410
Erik Språng242e22b2015-05-11 10:17:43 +0200411 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200412 // for video key-frames we want to send the RTCP before the large key-frame
413 // if we have a 100 ms margin
414 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
415 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000416
Erik Språng242e22b2015-05-11 10:17:43 +0200417 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200418 return true;
419 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200420 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200421 // wrap
422 return true;
423 }
424 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000425}
426
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000427int64_t RTCPSender::SendTimeOfSendReport(uint32_t sendReport) {
Erik Språng242e22b2015-05-11 10:17:43 +0200428 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000429
Erik Språng61be2a42015-04-27 13:32:52 +0200430 // This is only saved when we are the sender
Erik Språng242e22b2015-05-11 10:17:43 +0200431 if ((last_send_report_[0] == 0) || (sendReport == 0)) {
Erik Språng61be2a42015-04-27 13:32:52 +0200432 return 0; // will be ignored
433 } else {
434 for (int i = 0; i < RTCP_NUMBER_OF_SR; ++i) {
Erik Språng242e22b2015-05-11 10:17:43 +0200435 if (last_send_report_[i] == sendReport)
436 return last_rtcp_time_[i];
niklase@google.com470e71d2011-07-07 08:21:25 +0000437 }
Erik Språng61be2a42015-04-27 13:32:52 +0200438 }
439 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000440}
441
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000442bool RTCPSender::SendTimeOfXrRrReport(uint32_t mid_ntp,
443 int64_t* time_ms) const {
Erik Språng242e22b2015-05-11 10:17:43 +0200444 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000445
446 if (last_xr_rr_.empty()) {
447 return false;
448 }
449 std::map<uint32_t, int64_t>::const_iterator it = last_xr_rr_.find(mid_ntp);
450 if (it == last_xr_rr_.end()) {
451 return false;
452 }
453 *time_ms = it->second;
454 return true;
455}
456
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200457int32_t RTCPSender::AddReportBlock(const RTCPReportBlock& report_block) {
458 if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000459 LOG(LS_WARNING) << "Too many report blocks.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000460 return -1;
461 }
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200462 rtcp::ReportBlock* block = &report_blocks_[report_block.remoteSSRC];
463 block->To(report_block.remoteSSRC);
464 block->WithFractionLost(report_block.fractionLost);
danilchapdf948f02015-11-13 03:03:13 -0800465 if (!block->WithCumulativeLost(report_block.cumulativeLost)) {
466 LOG(LS_WARNING) << "Cumulative lost is oversized.";
467 return -1;
468 }
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200469 block->WithExtHighestSeqNum(report_block.extendedHighSeqNum);
470 block->WithJitter(report_block.jitter);
471 block->WithLastSr(report_block.lastSR);
472 block->WithDelayLastSr(report_block.delaySinceLastSR);
473
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000474 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000475}
476
Erik Språngf7c57762015-12-04 10:40:35 +0100477rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildSR(const RtcpContext& ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200478 for (int i = (RTCP_NUMBER_OF_SR - 2); i >= 0; i--) {
479 // shift old
Erik Språng242e22b2015-05-11 10:17:43 +0200480 last_send_report_[i + 1] = last_send_report_[i];
481 last_rtcp_time_[i + 1] = last_rtcp_time_[i];
Erik Språng61be2a42015-04-27 13:32:52 +0200482 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000483
Erik Språngf7c57762015-12-04 10:40:35 +0100484 last_rtcp_time_[0] = Clock::NtpToMs(ctx.ntp_sec_, ctx.ntp_frac_);
485 last_send_report_[0] = (ctx.ntp_sec_ << 16) + (ctx.ntp_frac_ >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000486
Erik Språng61be2a42015-04-27 13:32:52 +0200487 // The timestamp of this RTCP packet should be estimated as the timestamp of
488 // the frame being captured at this moment. We are calculating that
489 // timestamp as the last frame's timestamp + the time since the last frame
490 // was captured.
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200491 uint32_t rtp_timestamp =
492 start_timestamp_ + last_rtp_timestamp_ +
493 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) *
Erik Språngf7c57762015-12-04 10:40:35 +0100494 (ctx.feedback_state_.frequency_hz / 1000);
niklase@google.com470e71d2011-07-07 08:21:25 +0000495
Erik Språngf7c57762015-12-04 10:40:35 +0100496 rtcp::SenderReport* report = new rtcp::SenderReport();
497 report->From(ssrc_);
498 report->WithNtpSec(ctx.ntp_sec_);
499 report->WithNtpFrac(ctx.ntp_frac_);
500 report->WithRtpTimestamp(rtp_timestamp);
501 report->WithPacketCount(ctx.feedback_state_.packets_sent);
502 report->WithOctetCount(ctx.feedback_state_.media_bytes_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000503
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200504 for (auto it : report_blocks_)
Erik Språngf7c57762015-12-04 10:40:35 +0100505 report->WithReportBlock(it.second);
niklase@google.com470e71d2011-07-07 08:21:25 +0000506
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200507 report_blocks_.clear();
Erik Språngf7c57762015-12-04 10:40:35 +0100508
509 return rtc::scoped_ptr<rtcp::SenderReport>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000510}
511
Erik Språngf7c57762015-12-04 10:40:35 +0100512rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildSDES(
513 const RtcpContext& ctx) {
Erik Språng0ea42d32015-06-25 14:46:16 +0200514 size_t length_cname = cname_.length();
henrikg91d6ede2015-09-17 00:24:34 -0700515 RTC_CHECK_LT(length_cname, static_cast<size_t>(RTCP_CNAME_SIZE));
niklase@google.com470e71d2011-07-07 08:21:25 +0000516
Erik Språngf7c57762015-12-04 10:40:35 +0100517 rtcp::Sdes* sdes = new rtcp::Sdes();
518 sdes->WithCName(ssrc_, cname_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200519
520 for (const auto it : csrc_cnames_)
Erik Språngf7c57762015-12-04 10:40:35 +0100521 sdes->WithCName(it.first, it.second);
Erik Språng0ea42d32015-06-25 14:46:16 +0200522
Erik Språngf7c57762015-12-04 10:40:35 +0100523 return rtc::scoped_ptr<rtcp::Sdes>(sdes);
niklase@google.com470e71d2011-07-07 08:21:25 +0000524}
525
Erik Språngf7c57762015-12-04 10:40:35 +0100526rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildRR(const RtcpContext& ctx) {
527 rtcp::ReceiverReport* report = new rtcp::ReceiverReport();
528 report->From(ssrc_);
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200529 for (auto it : report_blocks_)
Erik Språngf7c57762015-12-04 10:40:35 +0100530 report->WithReportBlock(it.second);
Erik Språng61be2a42015-04-27 13:32:52 +0200531
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200532 report_blocks_.clear();
Erik Språngf7c57762015-12-04 10:40:35 +0100533 return rtc::scoped_ptr<rtcp::ReceiverReport>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000534}
535
Erik Språngf7c57762015-12-04 10:40:35 +0100536rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildPLI(const RtcpContext& ctx) {
537 rtcp::Pli* pli = new rtcp::Pli();
538 pli->From(ssrc_);
539 pli->To(remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200540
Erik Språng242e22b2015-05-11 10:17:43 +0200541 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
542 "RTCPSender::PLI");
543 ++packet_type_counter_.pli_packets;
544 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
545 ssrc_, packet_type_counter_.pli_packets);
546
Erik Språngf7c57762015-12-04 10:40:35 +0100547 return rtc::scoped_ptr<rtcp::Pli>(pli);
Erik Språng61be2a42015-04-27 13:32:52 +0200548}
549
Erik Språngf7c57762015-12-04 10:40:35 +0100550rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildFIR(const RtcpContext& ctx) {
551 if (!ctx.repeat_)
sprang62dae192015-08-05 02:35:35 -0700552 ++sequence_number_fir_; // Do not increase if repetition.
niklase@google.com470e71d2011-07-07 08:21:25 +0000553
Erik Språngf7c57762015-12-04 10:40:35 +0100554 rtcp::Fir* fir = new rtcp::Fir();
555 fir->From(ssrc_);
556 fir->To(remote_ssrc_);
557 fir->WithCommandSeqNum(sequence_number_fir_);
Erik Språng242e22b2015-05-11 10:17:43 +0200558
559 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
560 "RTCPSender::FIR");
561 ++packet_type_counter_.fir_packets;
562 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
563 ssrc_, packet_type_counter_.fir_packets);
564
Erik Språngf7c57762015-12-04 10:40:35 +0100565 return rtc::scoped_ptr<rtcp::Fir>(fir);
niklase@google.com470e71d2011-07-07 08:21:25 +0000566}
567
568/*
569 0 1 2 3
570 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
571 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
572 | First | Number | PictureID |
573 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
574*/
Erik Språngf7c57762015-12-04 10:40:35 +0100575rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildSLI(const RtcpContext& ctx) {
576 rtcp::Sli* sli = new rtcp::Sli();
577 sli->From(ssrc_);
578 sli->To(remote_ssrc_);
sprang0365a272015-08-11 01:02:37 -0700579 // Crop picture id to 6 least significant bits.
Erik Språngf7c57762015-12-04 10:40:35 +0100580 sli->WithPictureId(ctx.picture_id_ & 0x3F);
581 sli->WithFirstMb(0);
582 sli->WithNumberOfMb(0x1FFF); // 13 bits, only ones for now.
sprang0365a272015-08-11 01:02:37 -0700583
Erik Språngf7c57762015-12-04 10:40:35 +0100584 return rtc::scoped_ptr<rtcp::Sli>(sli);
niklase@google.com470e71d2011-07-07 08:21:25 +0000585}
586
587/*
588 0 1 2 3
589 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
590 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
591 | PB |0| Payload Type| Native RPSI bit string |
592 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
593 | defined per codec ... | Padding (0) |
594 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
595*/
596/*
597* Note: not generic made for VP8
598*/
Erik Språngf7c57762015-12-04 10:40:35 +0100599rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildRPSI(
600 const RtcpContext& ctx) {
601 if (ctx.feedback_state_.send_payload_type == 0xFF)
602 return nullptr;
Erik Språng242e22b2015-05-11 10:17:43 +0200603
Erik Språngf7c57762015-12-04 10:40:35 +0100604 rtcp::Rpsi* rpsi = new rtcp::Rpsi();
605 rpsi->From(ssrc_);
606 rpsi->To(remote_ssrc_);
607 rpsi->WithPayloadType(ctx.feedback_state_.send_payload_type);
608 rpsi->WithPictureId(ctx.picture_id_);
sprangcf7f54d2015-08-13 04:37:42 -0700609
Erik Språngf7c57762015-12-04 10:40:35 +0100610 return rtc::scoped_ptr<rtcp::Rpsi>(rpsi);
niklase@google.com470e71d2011-07-07 08:21:25 +0000611}
612
Erik Språngf7c57762015-12-04 10:40:35 +0100613rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildREMB(
614 const RtcpContext& ctx) {
615 rtcp::Remb* remb = new rtcp::Remb();
616 remb->From(ssrc_);
sprangdd4edc52015-08-21 04:21:51 -0700617 for (uint32_t ssrc : remb_ssrcs_)
Erik Språngf7c57762015-12-04 10:40:35 +0100618 remb->AppliesTo(ssrc);
619 remb->WithBitrateBps(remb_bitrate_);
Erik Språng61be2a42015-04-27 13:32:52 +0200620
Erik Språng242e22b2015-05-11 10:17:43 +0200621 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
622 "RTCPSender::REMB");
623
Erik Språngf7c57762015-12-04 10:40:35 +0100624 return rtc::scoped_ptr<rtcp::Remb>(remb);
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000625}
626
Erik Språng61be2a42015-04-27 13:32:52 +0200627void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
Erik Språng242e22b2015-05-11 10:17:43 +0200628 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
629 tmmbr_send_ = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000630}
631
Erik Språngf7c57762015-12-04 10:40:35 +0100632rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBR(
633 const RtcpContext& ctx) {
634 if (ctx.feedback_state_.module == nullptr)
635 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200636 // Before sending the TMMBR check the received TMMBN, only an owner is
637 // allowed to raise the bitrate:
638 // * If the sender is an owner of the TMMBN -> send TMMBR
639 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000640
Erik Språng61be2a42015-04-27 13:32:52 +0200641 // get current bounding set from RTCP receiver
642 bool tmmbrOwner = false;
643 // store in candidateSet, allocates one extra slot
Erik Språng242e22b2015-05-11 10:17:43 +0200644 TMMBRSet* candidateSet = tmmbr_help_.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000645
Erik Språng242e22b2015-05-11 10:17:43 +0200646 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
647 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
Erik Språng61be2a42015-04-27 13:32:52 +0200648 // since RTCPreceiver is not doing the reverse we should be fine
649 int32_t lengthOfBoundingSet =
Erik Språngf7c57762015-12-04 10:40:35 +0100650 ctx.feedback_state_.module->BoundingSet(tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +0000651
Erik Språng61be2a42015-04-27 13:32:52 +0200652 if (lengthOfBoundingSet > 0) {
653 for (int32_t i = 0; i < lengthOfBoundingSet; i++) {
Erik Språng242e22b2015-05-11 10:17:43 +0200654 if (candidateSet->Tmmbr(i) == tmmbr_send_ &&
655 candidateSet->PacketOH(i) == packet_oh_send_) {
Erik Språngf7c57762015-12-04 10:40:35 +0100656 // Do not send the same tuple.
657 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200658 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000659 }
Erik Språng61be2a42015-04-27 13:32:52 +0200660 if (!tmmbrOwner) {
661 // use received bounding set as candidate set
662 // add current tuple
Erik Språng242e22b2015-05-11 10:17:43 +0200663 candidateSet->SetEntry(lengthOfBoundingSet, tmmbr_send_, packet_oh_send_,
664 ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200665 int numCandidates = lengthOfBoundingSet + 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000666
Erik Språng61be2a42015-04-27 13:32:52 +0200667 // find bounding set
Erik Språngf7c57762015-12-04 10:40:35 +0100668 TMMBRSet* boundingSet = nullptr;
Erik Språng242e22b2015-05-11 10:17:43 +0200669 int numBoundingSet = tmmbr_help_.FindTMMBRBoundingSet(boundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200670 if (numBoundingSet > 0 || numBoundingSet <= numCandidates)
Erik Språng242e22b2015-05-11 10:17:43 +0200671 tmmbrOwner = tmmbr_help_.IsOwner(ssrc_, numBoundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200672 if (!tmmbrOwner) {
Erik Språngf7c57762015-12-04 10:40:35 +0100673 // Did not enter bounding set, no meaning to send this request.
674 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200675 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000676 }
Erik Språng61be2a42015-04-27 13:32:52 +0200677 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000678
Erik Språngf7c57762015-12-04 10:40:35 +0100679 if (!tmmbr_send_)
680 return nullptr;
sprang81a3e602015-08-21 05:30:11 -0700681
Erik Språngf7c57762015-12-04 10:40:35 +0100682 rtcp::Tmmbr* tmmbr = new rtcp::Tmmbr();
683 tmmbr->From(ssrc_);
684 tmmbr->To(remote_ssrc_);
685 tmmbr->WithBitrateKbps(tmmbr_send_);
686 tmmbr->WithOverhead(packet_oh_send_);
687
688 return rtc::scoped_ptr<rtcp::Tmmbr>(tmmbr);
Erik Språng61be2a42015-04-27 13:32:52 +0200689}
690
Erik Språngf7c57762015-12-04 10:40:35 +0100691rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBN(
692 const RtcpContext& ctx) {
Erik Språng242e22b2015-05-11 10:17:43 +0200693 TMMBRSet* boundingSet = tmmbr_help_.BoundingSetToSend();
Erik Språngf7c57762015-12-04 10:40:35 +0100694 if (boundingSet == nullptr)
695 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200696
Erik Språngf7c57762015-12-04 10:40:35 +0100697 rtcp::Tmmbn* tmmbn = new rtcp::Tmmbn();
698 tmmbn->From(ssrc_);
sprangd83df502015-08-27 01:05:08 -0700699 for (uint32_t i = 0; i < boundingSet->lengthOfSet(); i++) {
700 if (boundingSet->Tmmbr(i) > 0) {
Erik Språngf7c57762015-12-04 10:40:35 +0100701 tmmbn->WithTmmbr(boundingSet->Ssrc(i), boundingSet->Tmmbr(i),
702 boundingSet->PacketOH(i));
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000703 }
Erik Språng61be2a42015-04-27 13:32:52 +0200704 }
sprangd83df502015-08-27 01:05:08 -0700705
Erik Språngf7c57762015-12-04 10:40:35 +0100706 return rtc::scoped_ptr<rtcp::Tmmbn>(tmmbn);
niklase@google.com470e71d2011-07-07 08:21:25 +0000707}
708
Erik Språngf7c57762015-12-04 10:40:35 +0100709rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildAPP(const RtcpContext& ctx) {
710 rtcp::App* app = new rtcp::App();
711 app->From(ssrc_);
712 app->WithSubType(app_sub_type_);
713 app->WithName(app_name_);
714 app->WithData(app_data_.get(), app_length_);
Erik Språng521875a2015-09-01 10:11:16 +0200715
Erik Språngf7c57762015-12-04 10:40:35 +0100716 return rtc::scoped_ptr<rtcp::App>(app);
Erik Språng61be2a42015-04-27 13:32:52 +0200717}
718
Erik Språngf7c57762015-12-04 10:40:35 +0100719rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildNACK(
720 const RtcpContext& ctx) {
721 rtcp::Nack* nack = new rtcp::Nack();
722 nack->From(ssrc_);
723 nack->To(remote_ssrc_);
724 nack->WithList(ctx.nack_list_, ctx.nack_size_);
Erik Språng61be2a42015-04-27 13:32:52 +0200725
726 // Report stats.
727 NACKStringBuilder stringBuilder;
Erik Språngf7c57762015-12-04 10:40:35 +0100728 for (int idx = 0; idx < ctx.nack_size_; ++idx) {
729 stringBuilder.PushNACK(ctx.nack_list_[idx]);
730 nack_stats_.ReportRequest(ctx.nack_list_[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +0200731 }
Erik Språng61be2a42015-04-27 13:32:52 +0200732 packet_type_counter_.nack_requests = nack_stats_.requests();
733 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +0200734
735 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
736 "RTCPSender::NACK", "nacks",
737 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
738 ++packet_type_counter_.nack_packets;
739 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
740 ssrc_, packet_type_counter_.nack_packets);
741
Erik Språngf7c57762015-12-04 10:40:35 +0100742 return rtc::scoped_ptr<rtcp::Nack>(nack);
Erik Språng61be2a42015-04-27 13:32:52 +0200743}
744
Erik Språngf7c57762015-12-04 10:40:35 +0100745rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildBYE(const RtcpContext& ctx) {
746 rtcp::Bye* bye = new rtcp::Bye();
747 bye->From(ssrc_);
sprangd8ee4f92015-08-24 03:25:19 -0700748 for (uint32_t csrc : csrcs_)
Erik Språngf7c57762015-12-04 10:40:35 +0100749 bye->WithCsrc(csrc);
sprangd8ee4f92015-08-24 03:25:19 -0700750
Erik Språngf7c57762015-12-04 10:40:35 +0100751 return rtc::scoped_ptr<rtcp::Bye>(bye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000752}
753
Erik Språngf7c57762015-12-04 10:40:35 +0100754rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildReceiverReferenceTime(
755 const RtcpContext& ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200756 if (last_xr_rr_.size() >= RTCP_NUMBER_OF_SR)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000757 last_xr_rr_.erase(last_xr_rr_.begin());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000758 last_xr_rr_.insert(std::pair<uint32_t, int64_t>(
Erik Språngf7c57762015-12-04 10:40:35 +0100759 RTCPUtility::MidNtp(ctx.ntp_sec_, ctx.ntp_frac_),
760 Clock::NtpToMs(ctx.ntp_sec_, ctx.ntp_frac_)));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000761
Erik Språngf7c57762015-12-04 10:40:35 +0100762 rtcp::Xr* xr = new rtcp::Xr();
763 xr->From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000764
Erik Språngca28fdc2015-08-31 14:00:50 +0200765 rtcp::Rrtr rrtr;
Erik Språngf7c57762015-12-04 10:40:35 +0100766 rrtr.WithNtpSec(ctx.ntp_sec_);
767 rrtr.WithNtpFrac(ctx.ntp_frac_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000768
Erik Språngf7c57762015-12-04 10:40:35 +0100769 xr->WithRrtr(&rrtr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000770
Erik Språngca28fdc2015-08-31 14:00:50 +0200771 // TODO(sprang): Merge XR report sending to contain all of RRTR, DLRR, VOIP?
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000772
Erik Språngf7c57762015-12-04 10:40:35 +0100773 return rtc::scoped_ptr<rtcp::Xr>(xr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000774}
775
Erik Språngf7c57762015-12-04 10:40:35 +0100776rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildDlrr(
777 const RtcpContext& ctx) {
778 rtcp::Xr* xr = new rtcp::Xr();
779 xr->From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000780
Erik Språngca28fdc2015-08-31 14:00:50 +0200781 rtcp::Dlrr dlrr;
Erik Språngf7c57762015-12-04 10:40:35 +0100782 const RtcpReceiveTimeInfo& info = ctx.feedback_state_.last_xr_rr;
Erik Språngca28fdc2015-08-31 14:00:50 +0200783 dlrr.WithDlrrItem(info.sourceSSRC, info.lastRR, info.delaySinceLastRR);
784
Erik Språngf7c57762015-12-04 10:40:35 +0100785 xr->WithDlrr(&dlrr);
Erik Språngca28fdc2015-08-31 14:00:50 +0200786
Erik Språngf7c57762015-12-04 10:40:35 +0100787 return rtc::scoped_ptr<rtcp::Xr>(xr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000788}
789
Erik Språng242e22b2015-05-11 10:17:43 +0200790// TODO(sprang): Add a unit test for this, or remove if the code isn't used.
Erik Språngf7c57762015-12-04 10:40:35 +0100791rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildVoIPMetric(
792 const RtcpContext& context) {
793 rtcp::Xr* xr = new rtcp::Xr();
794 xr->From(ssrc_);
Erik Språngca28fdc2015-08-31 14:00:50 +0200795
796 rtcp::VoipMetric voip;
797 voip.To(remote_ssrc_);
798 voip.LossRate(xr_voip_metric_.lossRate);
799 voip.DiscardRate(xr_voip_metric_.discardRate);
800 voip.BurstDensity(xr_voip_metric_.burstDensity);
801 voip.GapDensity(xr_voip_metric_.gapDensity);
802 voip.BurstDuration(xr_voip_metric_.burstDuration);
803 voip.GapDuration(xr_voip_metric_.gapDuration);
804 voip.RoundTripDelay(xr_voip_metric_.roundTripDelay);
805 voip.EndSystemDelay(xr_voip_metric_.endSystemDelay);
806 voip.SignalLevel(xr_voip_metric_.signalLevel);
807 voip.NoiseLevel(xr_voip_metric_.noiseLevel);
808 voip.Rerl(xr_voip_metric_.RERL);
809 voip.Gmin(xr_voip_metric_.Gmin);
810 voip.Rfactor(xr_voip_metric_.Rfactor);
811 voip.ExtRfactor(xr_voip_metric_.extRfactor);
812 voip.MosLq(xr_voip_metric_.MOSLQ);
813 voip.MosCq(xr_voip_metric_.MOSCQ);
814 voip.RxConfig(xr_voip_metric_.RXconfig);
815 voip.JbNominal(xr_voip_metric_.JBnominal);
816 voip.JbMax(xr_voip_metric_.JBmax);
817 voip.JbAbsMax(xr_voip_metric_.JBabsMax);
818
Erik Språngf7c57762015-12-04 10:40:35 +0100819 xr->WithVoipMetric(&voip);
Erik Språngca28fdc2015-08-31 14:00:50 +0200820
Erik Språngf7c57762015-12-04 10:40:35 +0100821 return rtc::scoped_ptr<rtcp::Xr>(xr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000822}
823
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000824int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200825 RTCPPacketType packetType,
826 int32_t nack_size,
827 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000828 bool repeat,
829 uint64_t pictureID) {
Erik Språng242e22b2015-05-11 10:17:43 +0200830 return SendCompoundRTCP(
831 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
832 nack_size, nack_list, repeat, pictureID);
833}
834
835int32_t RTCPSender::SendCompoundRTCP(
836 const FeedbackState& feedback_state,
Erik Språngf7c57762015-12-04 10:40:35 +0100837 const std::set<RTCPPacketType>& packet_types,
Erik Språng242e22b2015-05-11 10:17:43 +0200838 int32_t nack_size,
839 const uint16_t* nack_list,
840 bool repeat,
841 uint64_t pictureID) {
Erik Språngf7c57762015-12-04 10:40:35 +0100842 PacketContainer container(transport_);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000843 {
Erik Språng242e22b2015-05-11 10:17:43 +0200844 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
pbosda903ea2015-10-02 02:36:56 -0700845 if (method_ == RtcpMode::kOff) {
Erik Språng61be2a42015-04-27 13:32:52 +0200846 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
847 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +0000848 }
Erik Språngf7c57762015-12-04 10:40:35 +0100849
850 // We need to send our NTP even if we haven't received any reports.
851 uint32_t ntp_sec;
852 uint32_t ntp_frac;
853 clock_->CurrentNtp(ntp_sec, ntp_frac);
854 RtcpContext context(feedback_state, nack_size, nack_list, repeat, pictureID,
855 ntp_sec, ntp_frac, &container);
856
857 PrepareReport(packet_types, feedback_state);
858
859 auto it = report_flags_.begin();
860 while (it != report_flags_.end()) {
861 auto builder_it = builders_.find(it->type);
862 RTC_DCHECK(builder_it != builders_.end());
863 if (it->is_volatile) {
864 report_flags_.erase(it++);
865 } else {
866 ++it;
867 }
868
869 BuilderFunc func = builder_it->second;
870 rtc::scoped_ptr<rtcp::RtcpPacket> packet = (this->*func)(context);
871 if (packet.get() == nullptr)
872 return -1;
873 container.Append(packet.release());
874 }
875
876 if (packet_type_counter_observer_ != nullptr) {
877 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
878 remote_ssrc_, packet_type_counter_);
879 }
880
881 RTC_DCHECK(AllVolatileFlagsConsumed());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000882 }
Erik Språng61be2a42015-04-27 13:32:52 +0200883
Erik Språngf7c57762015-12-04 10:40:35 +0100884 size_t bytes_sent = container.SendPackets();
885 return bytes_sent == 0 ? -1 : 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000886}
887
Erik Språngf7c57762015-12-04 10:40:35 +0100888void RTCPSender::PrepareReport(const std::set<RTCPPacketType>& packetTypes,
889 const FeedbackState& feedback_state) {
Erik Språng242e22b2015-05-11 10:17:43 +0200890 // Add all flags as volatile. Non volatile entries will not be overwritten
891 // and all new volatile flags added will be consumed by the end of this call.
892 SetFlags(packetTypes, true);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000893
Erik Språng61be2a42015-04-27 13:32:52 +0200894 if (packet_type_counter_.first_packet_time_ms == -1)
Erik Språng242e22b2015-05-11 10:17:43 +0200895 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språng61be2a42015-04-27 13:32:52 +0200896
Erik Språng242e22b2015-05-11 10:17:43 +0200897 bool generate_report;
898 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
899 // Report type already explicitly set, don't automatically populate.
900 generate_report = true;
henrikg91d6ede2015-09-17 00:24:34 -0700901 RTC_DCHECK(ConsumeFlag(kRtcpReport) == false);
Erik Språng242e22b2015-05-11 10:17:43 +0200902 } else {
903 generate_report =
pbosda903ea2015-10-02 02:36:56 -0700904 (ConsumeFlag(kRtcpReport) && method_ == RtcpMode::kReducedSize) ||
905 method_ == RtcpMode::kCompound;
Erik Språng242e22b2015-05-11 10:17:43 +0200906 if (generate_report)
907 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000908 }
909
Erik Språng0ea42d32015-06-25 14:46:16 +0200910 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
Erik Språng242e22b2015-05-11 10:17:43 +0200911 SetFlag(kRtcpSdes, true);
912
Erik Språng242e22b2015-05-11 10:17:43 +0200913 if (generate_report) {
914 if (!sending_ && xr_send_receiver_reference_time_enabled_)
915 SetFlag(kRtcpXrReceiverReferenceTime, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200916 if (feedback_state.has_last_xr_rr)
Erik Språng242e22b2015-05-11 10:17:43 +0200917 SetFlag(kRtcpXrDlrrReportBlock, true);
918
919 // generate next time to send an RTCP report
Erik Språng61be2a42015-04-27 13:32:52 +0200920 // seeded from RTP constructor
921 int32_t random = rand() % 1000;
922 int32_t timeToNext = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000923
Erik Språng242e22b2015-05-11 10:17:43 +0200924 if (audio_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200925 timeToNext = (RTCP_INTERVAL_AUDIO_MS / 2) +
926 (RTCP_INTERVAL_AUDIO_MS * random / 1000);
927 } else {
928 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
Erik Språng242e22b2015-05-11 10:17:43 +0200929 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200930 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
931 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
932 if (send_bitrate_kbit != 0)
933 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000934 }
Erik Språng61be2a42015-04-27 13:32:52 +0200935 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
936 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
937 timeToNext = (minIntervalMs / 2) + (minIntervalMs * random / 1000);
938 }
Erik Språng242e22b2015-05-11 10:17:43 +0200939 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000940
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000941 StatisticianMap statisticians =
942 receive_statistics_->GetActiveStatisticians();
943 if (!statisticians.empty()) {
Erik Språng61be2a42015-04-27 13:32:52 +0200944 for (auto it = statisticians.begin(); it != statisticians.end(); ++it) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000945 RTCPReportBlock report_block;
Erik Språngf7c57762015-12-04 10:40:35 +0100946 if (PrepareReportBlock(feedback_state, it->first, it->second,
947 &report_block)) {
danilchapdf948f02015-11-13 03:03:13 -0800948 // TODO(danilchap) AddReportBlock may fail (for 2 different reasons).
949 // Probably it shouldn't be ignored.
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200950 AddReportBlock(report_block);
Erik Språng61be2a42015-04-27 13:32:52 +0200951 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000952 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000953 }
954 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000955}
956
Erik Språngf7c57762015-12-04 10:40:35 +0100957bool RTCPSender::PrepareReportBlock(const FeedbackState& feedback_state,
958 uint32_t ssrc,
959 StreamStatistician* statistician,
960 RTCPReportBlock* report_block) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000961 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000962 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000963 if (!statistician->GetStatistics(&stats, true))
964 return false;
965 report_block->fractionLost = stats.fraction_lost;
966 report_block->cumulativeLost = stats.cumulative_lost;
967 report_block->extendedHighSeqNum =
968 stats.extended_max_sequence_number;
969 report_block->jitter = stats.jitter;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200970 report_block->remoteSSRC = ssrc;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000971
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200972 // TODO(sprang): Do we really need separate time stamps for each report?
973 // Get our NTP as late as possible to avoid a race.
974 uint32_t ntp_secs;
975 uint32_t ntp_frac;
976 clock_->CurrentNtp(ntp_secs, ntp_frac);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000977
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200978 // Delay since last received report.
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000979 uint32_t delaySinceLastReceivedSR = 0;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000980 if ((feedback_state.last_rr_ntp_secs != 0) ||
981 (feedback_state.last_rr_ntp_frac != 0)) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200982 // Get the 16 lowest bits of seconds and the 16 highest bits of fractions.
983 uint32_t now = ntp_secs & 0x0000FFFF;
Erik Språng61be2a42015-04-27 13:32:52 +0200984 now <<= 16;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200985 now += (ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000986
Erik Språng61be2a42015-04-27 13:32:52 +0200987 uint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
988 receiveTime <<= 16;
989 receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000990
991 delaySinceLastReceivedSR = now-receiveTime;
992 }
993 report_block->delaySinceLastSR = delaySinceLastReceivedSR;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000994 report_block->lastSR = feedback_state.remote_sr;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000995 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000996}
997
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000998void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
999 assert(csrcs.size() <= kRtpCsrcSize);
Erik Språng242e22b2015-05-11 10:17:43 +02001000 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001001 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +00001002}
1003
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001004int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
1005 uint32_t name,
1006 const uint8_t* data,
1007 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +02001008 if (length % 4 != 0) {
1009 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
1010 return -1;
1011 }
Erik Språng242e22b2015-05-11 10:17:43 +02001012 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +00001013
Erik Språng242e22b2015-05-11 10:17:43 +02001014 SetFlag(kRtcpApp, true);
1015 app_sub_type_ = subType;
1016 app_name_ = name;
1017 app_data_.reset(new uint8_t[length]);
1018 app_length_ = length;
1019 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +02001020 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001021}
1022
Erik Språng61be2a42015-04-27 13:32:52 +02001023int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
Erik Språng242e22b2015-05-11 10:17:43 +02001024 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1025 memcpy(&xr_voip_metric_, VoIPMetric, sizeof(RTCPVoIPMetric));
niklase@google.com470e71d2011-07-07 08:21:25 +00001026
Erik Språng242e22b2015-05-11 10:17:43 +02001027 SetFlag(kRtcpXrVoipMetric, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001028 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001029}
1030
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001031void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +02001032 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1033 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001034}
1035
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00001036bool RTCPSender::RtcpXrReceiverReferenceTime() const {
Erik Språng242e22b2015-05-11 10:17:43 +02001037 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1038 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00001039}
1040
niklase@google.com470e71d2011-07-07 08:21:25 +00001041// no callbacks allowed inside this function
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001042int32_t RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
1043 uint32_t maxBitrateKbit) {
Erik Språng242e22b2015-05-11 10:17:43 +02001044 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +00001045
Erik Språng242e22b2015-05-11 10:17:43 +02001046 if (0 == tmmbr_help_.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit)) {
1047 SetFlag(kRtcpTmmbn, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001048 return 0;
1049 }
1050 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001051}
Erik Språng61be2a42015-04-27 13:32:52 +02001052
Erik Språng242e22b2015-05-11 10:17:43 +02001053void RTCPSender::SetFlag(RTCPPacketType type, bool is_volatile) {
1054 report_flags_.insert(ReportFlag(type, is_volatile));
1055}
1056
1057void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
1058 bool is_volatile) {
1059 for (RTCPPacketType type : types)
1060 SetFlag(type, is_volatile);
1061}
1062
1063bool RTCPSender::IsFlagPresent(RTCPPacketType type) const {
1064 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
1065}
1066
1067bool RTCPSender::ConsumeFlag(RTCPPacketType type, bool forced) {
1068 auto it = report_flags_.find(ReportFlag(type, false));
1069 if (it == report_flags_.end())
1070 return false;
1071 if (it->is_volatile || forced)
1072 report_flags_.erase((it));
1073 return true;
1074}
1075
1076bool RTCPSender::AllVolatileFlagsConsumed() const {
1077 for (const ReportFlag& flag : report_flags_) {
1078 if (flag.is_volatile)
1079 return false;
1080 }
1081 return true;
1082}
1083
sprang233bd872015-09-08 13:25:16 -07001084bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
sprang233bd872015-09-08 13:25:16 -07001085 class Sender : public rtcp::RtcpPacket::PacketReadyCallback {
1086 public:
Peter Boströmac547a62015-09-17 23:03:57 +02001087 Sender(Transport* transport)
1088 : transport_(transport), send_failure_(false) {}
sprang233bd872015-09-08 13:25:16 -07001089
1090 void OnPacketReady(uint8_t* data, size_t length) override {
pbos2d566682015-09-28 09:59:31 -07001091 if (!transport_->SendRtcp(data, length))
sprang233bd872015-09-08 13:25:16 -07001092 send_failure_ = true;
1093 }
1094
1095 Transport* const transport_;
sprang233bd872015-09-08 13:25:16 -07001096 bool send_failure_;
sprang86fd9ed2015-09-29 04:45:43 -07001097 } sender(transport_);
sprang233bd872015-09-08 13:25:16 -07001098
1099 uint8_t buffer[IP_PACKET_SIZE];
1100 return packet.BuildExternalBuffer(buffer, IP_PACKET_SIZE, &sender) &&
1101 !sender.send_failure_;
1102}
1103
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001104} // namespace webrtc