blob: ac3f337998d5dbea93638587bad2bce215160a57 [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"
Danil Chapovalov97f7e132015-12-04 16:13:30 +010028#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
sprang233bd872015-09-08 13:25:16 -070029#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
tommie4f96502015-10-20 23:00:48 -070030#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010031#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000032
niklase@google.com470e71d2011-07-07 08:21:25 +000033namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000034
35using RTCPUtility::RTCPCnameInformation;
36
Erik Språng61be2a42015-04-27 13:32:52 +020037NACKStringBuilder::NACKStringBuilder()
Erik Språng242e22b2015-05-11 10:17:43 +020038 : stream_(""), count_(0), prevNack_(0), consecutive_(false) {
edjee@google.com79b02892013-04-04 19:43:34 +000039}
40
pbos@webrtc.orgf3e4cee2013-07-31 15:17:19 +000041NACKStringBuilder::~NACKStringBuilder() {}
42
pbos@webrtc.org2f446732013-04-08 11:08:41 +000043void NACKStringBuilder::PushNACK(uint16_t nack)
edjee@google.com79b02892013-04-04 19:43:34 +000044{
Erik Språng242e22b2015-05-11 10:17:43 +020045 if (count_ == 0) {
46 stream_ << nack;
47 } else if (nack == prevNack_ + 1) {
48 consecutive_ = true;
Erik Språng61be2a42015-04-27 13:32:52 +020049 } else {
Erik Språng242e22b2015-05-11 10:17:43 +020050 if (consecutive_) {
51 stream_ << "-" << prevNack_;
52 consecutive_ = false;
edjee@google.com79b02892013-04-04 19:43:34 +000053 }
Erik Språng242e22b2015-05-11 10:17:43 +020054 stream_ << "," << nack;
Erik Språng61be2a42015-04-27 13:32:52 +020055 }
Erik Språng242e22b2015-05-11 10:17:43 +020056 count_++;
57 prevNack_ = nack;
edjee@google.com79b02892013-04-04 19:43:34 +000058}
59
Erik Språng61be2a42015-04-27 13:32:52 +020060std::string NACKStringBuilder::GetResult() {
Erik Språng242e22b2015-05-11 10:17:43 +020061 if (consecutive_) {
62 stream_ << "-" << prevNack_;
63 consecutive_ = false;
Erik Språng61be2a42015-04-27 13:32:52 +020064 }
Erik Språng242e22b2015-05-11 10:17:43 +020065 return stream_.str();
edjee@google.com79b02892013-04-04 19:43:34 +000066}
67
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000068RTCPSender::FeedbackState::FeedbackState()
69 : send_payload_type(0),
70 frequency_hz(0),
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +000071 packets_sent(0),
72 media_bytes_sent(0),
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000073 send_bitrate(0),
74 last_rr_ntp_secs(0),
75 last_rr_ntp_frac(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000076 remote_sr(0),
Erik Språng61be2a42015-04-27 13:32:52 +020077 has_last_xr_rr(false),
78 module(nullptr) {
79}
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000080
Erik Språngf7c57762015-12-04 10:40:35 +010081class PacketContainer : public rtcp::Empty,
82 public rtcp::RtcpPacket::PacketReadyCallback {
83 public:
84 explicit PacketContainer(Transport* transport)
85 : transport_(transport), bytes_sent_(0) {}
86 virtual ~PacketContainer() {
87 for (RtcpPacket* packet : appended_packets_)
88 delete packet;
89 }
90
91 void OnPacketReady(uint8_t* data, size_t length) override {
92 if (transport_->SendRtcp(data, length))
93 bytes_sent_ += length;
94 }
95
96 size_t SendPackets() {
97 rtcp::Empty::Build(this);
98 return bytes_sent_;
99 }
100
101 private:
102 Transport* transport_;
103 size_t bytes_sent_;
104};
105
106class RTCPSender::RtcpContext {
107 public:
Erik Språng242e22b2015-05-11 10:17:43 +0200108 RtcpContext(const FeedbackState& feedback_state,
109 int32_t nack_size,
110 const uint16_t* nack_list,
111 bool repeat,
112 uint64_t picture_id,
Erik Språngf7c57762015-12-04 10:40:35 +0100113 uint32_t ntp_sec,
114 uint32_t ntp_frac,
115 PacketContainer* container)
116 : feedback_state_(feedback_state),
117 nack_size_(nack_size),
118 nack_list_(nack_list),
119 repeat_(repeat),
120 picture_id_(picture_id),
121 ntp_sec_(ntp_sec),
122 ntp_frac_(ntp_frac),
123 container_(container) {}
Erik Språng242e22b2015-05-11 10:17:43 +0200124
Erik Språngf7c57762015-12-04 10:40:35 +0100125 virtual ~RtcpContext() {}
Erik Språng242e22b2015-05-11 10:17:43 +0200126
Erik Språngf7c57762015-12-04 10:40:35 +0100127 const FeedbackState& feedback_state_;
128 const int32_t nack_size_;
129 const uint16_t* nack_list_;
130 const bool repeat_;
131 const uint64_t picture_id_;
132 const uint32_t ntp_sec_;
133 const uint32_t ntp_frac_;
Erik Språng242e22b2015-05-11 10:17:43 +0200134
Erik Språngf7c57762015-12-04 10:40:35 +0100135 PacketContainer* const container_;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200136};
137
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000138RTCPSender::RTCPSender(
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000139 bool audio,
140 Clock* clock,
141 ReceiveStatistics* receive_statistics,
sprang86fd9ed2015-09-29 04:45:43 -0700142 RtcpPacketTypeCounterObserver* packet_type_counter_observer,
143 Transport* outgoing_transport)
Peter Boströmac547a62015-09-17 23:03:57 +0200144 : audio_(audio),
Erik Språng242e22b2015-05-11 10:17:43 +0200145 clock_(clock),
pbosda903ea2015-10-02 02:36:56 -0700146 method_(RtcpMode::kOff),
sprang86fd9ed2015-09-29 04:45:43 -0700147 transport_(outgoing_transport),
niklase@google.com470e71d2011-07-07 08:21:25 +0000148
Erik Språng242e22b2015-05-11 10:17:43 +0200149 critical_section_rtcp_sender_(
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000150 CriticalSectionWrapper::CreateCriticalSection()),
Erik Språng242e22b2015-05-11 10:17:43 +0200151 using_nack_(false),
152 sending_(false),
153 remb_enabled_(false),
Erik Språng242e22b2015-05-11 10:17:43 +0200154 next_time_to_send_rtcp_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000155 start_timestamp_(0),
156 last_rtp_timestamp_(0),
157 last_frame_capture_time_ms_(-1),
Erik Språng242e22b2015-05-11 10:17:43 +0200158 ssrc_(0),
159 remote_ssrc_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000160 receive_statistics_(receive_statistics),
niklase@google.com470e71d2011-07-07 08:21:25 +0000161
Erik Språng242e22b2015-05-11 10:17:43 +0200162 sequence_number_fir_(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000163
Erik Språng242e22b2015-05-11 10:17:43 +0200164 remb_bitrate_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000165
Erik Språng242e22b2015-05-11 10:17:43 +0200166 tmmbr_help_(),
167 tmmbr_send_(0),
168 packet_oh_send_(0),
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000169
Erik Språng242e22b2015-05-11 10:17:43 +0200170 app_sub_type_(0),
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200171 app_name_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200172 app_data_(nullptr),
173 app_length_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000174
Erik Språng242e22b2015-05-11 10:17:43 +0200175 xr_send_receiver_reference_time_enabled_(false),
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000176 packet_type_counter_observer_(packet_type_counter_observer) {
Erik Språng242e22b2015-05-11 10:17:43 +0200177 memset(last_send_report_, 0, sizeof(last_send_report_));
178 memset(last_rtcp_time_, 0, sizeof(last_rtcp_time_));
sprang86fd9ed2015-09-29 04:45:43 -0700179 RTC_DCHECK(transport_ != nullptr);
Erik Språng242e22b2015-05-11 10:17:43 +0200180
181 builders_[kRtcpSr] = &RTCPSender::BuildSR;
182 builders_[kRtcpRr] = &RTCPSender::BuildRR;
Erik Språng0ea42d32015-06-25 14:46:16 +0200183 builders_[kRtcpSdes] = &RTCPSender::BuildSDES;
Erik Språng242e22b2015-05-11 10:17:43 +0200184 builders_[kRtcpPli] = &RTCPSender::BuildPLI;
185 builders_[kRtcpFir] = &RTCPSender::BuildFIR;
186 builders_[kRtcpSli] = &RTCPSender::BuildSLI;
187 builders_[kRtcpRpsi] = &RTCPSender::BuildRPSI;
188 builders_[kRtcpRemb] = &RTCPSender::BuildREMB;
189 builders_[kRtcpBye] = &RTCPSender::BuildBYE;
190 builders_[kRtcpApp] = &RTCPSender::BuildAPP;
191 builders_[kRtcpTmmbr] = &RTCPSender::BuildTMMBR;
192 builders_[kRtcpTmmbn] = &RTCPSender::BuildTMMBN;
193 builders_[kRtcpNack] = &RTCPSender::BuildNACK;
194 builders_[kRtcpXrVoipMetric] = &RTCPSender::BuildVoIPMetric;
195 builders_[kRtcpXrReceiverReferenceTime] =
196 &RTCPSender::BuildReceiverReferenceTime;
197 builders_[kRtcpXrDlrrReportBlock] = &RTCPSender::BuildDlrr;
niklase@google.com470e71d2011-07-07 08:21:25 +0000198}
199
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000200RTCPSender::~RTCPSender() {
niklase@google.com470e71d2011-07-07 08:21:25 +0000201}
202
pbosda903ea2015-10-02 02:36:56 -0700203RtcpMode RTCPSender::Status() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200204 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
205 return method_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000206}
207
pbosda903ea2015-10-02 02:36:56 -0700208void RTCPSender::SetRTCPStatus(RtcpMode method) {
Erik Språng242e22b2015-05-11 10:17:43 +0200209 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
210 method_ = method;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000211
pbosda903ea2015-10-02 02:36:56 -0700212 if (method == RtcpMode::kOff)
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000213 return;
Erik Språng242e22b2015-05-11 10:17:43 +0200214 next_time_to_send_rtcp_ =
215 clock_->TimeInMilliseconds() +
216 (audio_ ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000217}
218
Erik Språng61be2a42015-04-27 13:32:52 +0200219bool RTCPSender::Sending() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200220 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
221 return sending_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000222}
223
Erik Språng61be2a42015-04-27 13:32:52 +0200224int32_t RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
225 bool sending) {
226 bool sendRTCPBye = false;
227 {
Erik Språng242e22b2015-05-11 10:17:43 +0200228 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000229
pbosda903ea2015-10-02 02:36:56 -0700230 if (method_ != RtcpMode::kOff) {
Erik Språng242e22b2015-05-11 10:17:43 +0200231 if (sending == false && sending_ == true) {
Erik Språng61be2a42015-04-27 13:32:52 +0200232 // Trigger RTCP bye
233 sendRTCPBye = true;
234 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000235 }
Erik Språng242e22b2015-05-11 10:17:43 +0200236 sending_ = sending;
Erik Språng61be2a42015-04-27 13:32:52 +0200237 }
238 if (sendRTCPBye)
239 return SendRTCP(feedback_state, kRtcpBye);
240 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000241}
242
Erik Språng61be2a42015-04-27 13:32:52 +0200243bool RTCPSender::REMB() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200244 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
245 return remb_enabled_;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000246}
247
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000248void RTCPSender::SetREMBStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200249 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
250 remb_enabled_ = enable;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000251}
252
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000253void RTCPSender::SetREMBData(uint32_t bitrate,
254 const std::vector<uint32_t>& ssrcs) {
Erik Språng242e22b2015-05-11 10:17:43 +0200255 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
256 remb_bitrate_ = bitrate;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000257 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000258
Erik Språng242e22b2015-05-11 10:17:43 +0200259 if (remb_enabled_)
260 SetFlag(kRtcpRemb, false);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000261 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
262 // throttled by the caller.
Erik Språng242e22b2015-05-11 10:17:43 +0200263 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000264}
265
Erik Språng61be2a42015-04-27 13:32:52 +0200266bool RTCPSender::TMMBR() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200267 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
268 return IsFlagPresent(RTCPPacketType::kRtcpTmmbr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000269}
270
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000271void RTCPSender::SetTMMBRStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200272 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
273 if (enable) {
274 SetFlag(RTCPPacketType::kRtcpTmmbr, false);
275 } else {
276 ConsumeFlag(RTCPPacketType::kRtcpTmmbr, true);
277 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000278}
279
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000280void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
Erik Språng242e22b2015-05-11 10:17:43 +0200281 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000282 start_timestamp_ = start_timestamp;
283}
284
285void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
286 int64_t capture_time_ms) {
Erik Språng242e22b2015-05-11 10:17:43 +0200287 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000288 last_rtp_timestamp_ = rtp_timestamp;
289 if (capture_time_ms < 0) {
290 // We don't currently get a capture time from VoiceEngine.
Erik Språng242e22b2015-05-11 10:17:43 +0200291 last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000292 } else {
293 last_frame_capture_time_ms_ = capture_time_ms;
294 }
295}
296
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000297void RTCPSender::SetSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200298 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000299
Erik Språng242e22b2015-05-11 10:17:43 +0200300 if (ssrc_ != 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200301 // not first SetSSRC, probably due to a collision
302 // schedule a new RTCP report
303 // make sure that we send a RTP packet
Erik Språng242e22b2015-05-11 10:17:43 +0200304 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
Erik Språng61be2a42015-04-27 13:32:52 +0200305 }
Erik Språng242e22b2015-05-11 10:17:43 +0200306 ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000307}
308
Erik Språng61be2a42015-04-27 13:32:52 +0200309void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200310 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
311 remote_ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000312}
313
Peter Boström9ba52f82015-06-01 14:12:28 +0200314int32_t RTCPSender::SetCNAME(const char* c_name) {
315 if (!c_name)
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000316 return -1;
317
henrikg91d6ede2015-09-17 00:24:34 -0700318 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
Erik Språng242e22b2015-05-11 10:17:43 +0200319 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200320 cname_ = c_name;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000321 return 0;
322}
323
Erik Språng0ea42d32015-06-25 14:46:16 +0200324int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC, const char* c_name) {
325 assert(c_name);
henrikg91d6ede2015-09-17 00:24:34 -0700326 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
Erik Språng242e22b2015-05-11 10:17:43 +0200327 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200328 if (csrc_cnames_.size() >= kRtpCsrcSize)
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000329 return -1;
Erik Språng0ea42d32015-06-25 14:46:16 +0200330
331 csrc_cnames_[SSRC] = c_name;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000332 return 0;
333}
334
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000335int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
Erik Språng242e22b2015-05-11 10:17:43 +0200336 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200337 auto it = csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000338
Erik Språng242e22b2015-05-11 10:17:43 +0200339 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000340 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200341
Erik Språng242e22b2015-05-11 10:17:43 +0200342 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000343 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000344}
345
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000346bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
niklase@google.com470e71d2011-07-07 08:21:25 +0000347/*
348 For audio we use a fix 5 sec interval
349
350 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000351 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
352 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000353
354
355From RFC 3550
356
357 MAX RTCP BW is 5% if the session BW
358 A send report is approximately 65 bytes inc CNAME
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000359 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000360
361 The RECOMMENDED value for the reduced minimum in seconds is 360
362 divided by the session bandwidth in kilobits/second. This minimum
363 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
364
365 If the participant has not yet sent an RTCP packet (the variable
366 initial is true), the constant Tmin is set to 2.5 seconds, else it
367 is set to 5 seconds.
368
369 The interval between RTCP packets is varied randomly over the
370 range [0.5,1.5] times the calculated interval to avoid unintended
371 synchronization of all participants
372
373 if we send
374 If the participant is a sender (we_sent true), the constant C is
375 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
376 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
377 number of senders.
378
379 if we receive only
380 If we_sent is not true, the constant C is set
381 to the average RTCP packet size divided by 75% of the RTCP
382 bandwidth. The constant n is set to the number of receivers
383 (members - senders). If the number of senders is greater than
384 25%, senders and receivers are treated together.
385
386 reconsideration NOT required for peer-to-peer
387 "timer reconsideration" is
388 employed. This algorithm implements a simple back-off mechanism
389 which causes users to hold back RTCP packet transmission if the
390 group sizes are increasing.
391
392 n = number of members
393 C = avg_size/(rtcpBW/4)
394
395 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
396
397 4. The calculated interval T is set to a number uniformly distributed
398 between 0.5 and 1.5 times the deterministic calculated interval.
399
400 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
401 for the fact that the timer reconsideration algorithm converges to
402 a value of the RTCP bandwidth below the intended average
403*/
404
Erik Språng242e22b2015-05-11 10:17:43 +0200405 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000406
Erik Språng242e22b2015-05-11 10:17:43 +0200407 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
xians@webrtc.org8738d272011-11-25 13:43:53 +0000408
pbosda903ea2015-10-02 02:36:56 -0700409 if (method_ == RtcpMode::kOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000410 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000411
Erik Språng242e22b2015-05-11 10:17:43 +0200412 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200413 // for video key-frames we want to send the RTCP before the large key-frame
414 // if we have a 100 ms margin
415 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
416 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000417
Erik Språng242e22b2015-05-11 10:17:43 +0200418 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200419 return true;
420 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200421 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200422 // wrap
423 return true;
424 }
425 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000426}
427
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000428int64_t RTCPSender::SendTimeOfSendReport(uint32_t sendReport) {
Erik Språng242e22b2015-05-11 10:17:43 +0200429 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000430
Erik Språng61be2a42015-04-27 13:32:52 +0200431 // This is only saved when we are the sender
Erik Språng242e22b2015-05-11 10:17:43 +0200432 if ((last_send_report_[0] == 0) || (sendReport == 0)) {
Erik Språng61be2a42015-04-27 13:32:52 +0200433 return 0; // will be ignored
434 } else {
435 for (int i = 0; i < RTCP_NUMBER_OF_SR; ++i) {
Erik Språng242e22b2015-05-11 10:17:43 +0200436 if (last_send_report_[i] == sendReport)
437 return last_rtcp_time_[i];
niklase@google.com470e71d2011-07-07 08:21:25 +0000438 }
Erik Språng61be2a42015-04-27 13:32:52 +0200439 }
440 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000441}
442
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000443bool RTCPSender::SendTimeOfXrRrReport(uint32_t mid_ntp,
444 int64_t* time_ms) const {
Erik Språng242e22b2015-05-11 10:17:43 +0200445 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000446
447 if (last_xr_rr_.empty()) {
448 return false;
449 }
450 std::map<uint32_t, int64_t>::const_iterator it = last_xr_rr_.find(mid_ntp);
451 if (it == last_xr_rr_.end()) {
452 return false;
453 }
454 *time_ms = it->second;
455 return true;
456}
457
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200458int32_t RTCPSender::AddReportBlock(const RTCPReportBlock& report_block) {
459 if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000460 LOG(LS_WARNING) << "Too many report blocks.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000461 return -1;
462 }
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200463 rtcp::ReportBlock* block = &report_blocks_[report_block.remoteSSRC];
464 block->To(report_block.remoteSSRC);
465 block->WithFractionLost(report_block.fractionLost);
danilchapdf948f02015-11-13 03:03:13 -0800466 if (!block->WithCumulativeLost(report_block.cumulativeLost)) {
467 LOG(LS_WARNING) << "Cumulative lost is oversized.";
468 return -1;
469 }
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200470 block->WithExtHighestSeqNum(report_block.extendedHighSeqNum);
471 block->WithJitter(report_block.jitter);
472 block->WithLastSr(report_block.lastSR);
473 block->WithDelayLastSr(report_block.delaySinceLastSR);
474
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000475 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000476}
477
Erik Språngf7c57762015-12-04 10:40:35 +0100478rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildSR(const RtcpContext& ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200479 for (int i = (RTCP_NUMBER_OF_SR - 2); i >= 0; i--) {
480 // shift old
Erik Språng242e22b2015-05-11 10:17:43 +0200481 last_send_report_[i + 1] = last_send_report_[i];
482 last_rtcp_time_[i + 1] = last_rtcp_time_[i];
Erik Språng61be2a42015-04-27 13:32:52 +0200483 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000484
Erik Språngf7c57762015-12-04 10:40:35 +0100485 last_rtcp_time_[0] = Clock::NtpToMs(ctx.ntp_sec_, ctx.ntp_frac_);
486 last_send_report_[0] = (ctx.ntp_sec_ << 16) + (ctx.ntp_frac_ >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000487
Erik Språng61be2a42015-04-27 13:32:52 +0200488 // The timestamp of this RTCP packet should be estimated as the timestamp of
489 // the frame being captured at this moment. We are calculating that
490 // timestamp as the last frame's timestamp + the time since the last frame
491 // was captured.
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200492 uint32_t rtp_timestamp =
493 start_timestamp_ + last_rtp_timestamp_ +
494 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) *
Erik Språngf7c57762015-12-04 10:40:35 +0100495 (ctx.feedback_state_.frequency_hz / 1000);
niklase@google.com470e71d2011-07-07 08:21:25 +0000496
Erik Språngf7c57762015-12-04 10:40:35 +0100497 rtcp::SenderReport* report = new rtcp::SenderReport();
498 report->From(ssrc_);
499 report->WithNtpSec(ctx.ntp_sec_);
500 report->WithNtpFrac(ctx.ntp_frac_);
501 report->WithRtpTimestamp(rtp_timestamp);
502 report->WithPacketCount(ctx.feedback_state_.packets_sent);
503 report->WithOctetCount(ctx.feedback_state_.media_bytes_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000504
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200505 for (auto it : report_blocks_)
Erik Språngf7c57762015-12-04 10:40:35 +0100506 report->WithReportBlock(it.second);
niklase@google.com470e71d2011-07-07 08:21:25 +0000507
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200508 report_blocks_.clear();
Erik Språngf7c57762015-12-04 10:40:35 +0100509
510 return rtc::scoped_ptr<rtcp::SenderReport>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000511}
512
Erik Språngf7c57762015-12-04 10:40:35 +0100513rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildSDES(
514 const RtcpContext& ctx) {
Erik Språng0ea42d32015-06-25 14:46:16 +0200515 size_t length_cname = cname_.length();
henrikg91d6ede2015-09-17 00:24:34 -0700516 RTC_CHECK_LT(length_cname, static_cast<size_t>(RTCP_CNAME_SIZE));
niklase@google.com470e71d2011-07-07 08:21:25 +0000517
Erik Språngf7c57762015-12-04 10:40:35 +0100518 rtcp::Sdes* sdes = new rtcp::Sdes();
519 sdes->WithCName(ssrc_, cname_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200520
521 for (const auto it : csrc_cnames_)
Erik Språngf7c57762015-12-04 10:40:35 +0100522 sdes->WithCName(it.first, it.second);
Erik Språng0ea42d32015-06-25 14:46:16 +0200523
Erik Språngf7c57762015-12-04 10:40:35 +0100524 return rtc::scoped_ptr<rtcp::Sdes>(sdes);
niklase@google.com470e71d2011-07-07 08:21:25 +0000525}
526
Erik Språngf7c57762015-12-04 10:40:35 +0100527rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildRR(const RtcpContext& ctx) {
528 rtcp::ReceiverReport* report = new rtcp::ReceiverReport();
529 report->From(ssrc_);
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200530 for (auto it : report_blocks_)
Erik Språngf7c57762015-12-04 10:40:35 +0100531 report->WithReportBlock(it.second);
Erik Språng61be2a42015-04-27 13:32:52 +0200532
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200533 report_blocks_.clear();
Erik Språngf7c57762015-12-04 10:40:35 +0100534 return rtc::scoped_ptr<rtcp::ReceiverReport>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000535}
536
Erik Språngf7c57762015-12-04 10:40:35 +0100537rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildPLI(const RtcpContext& ctx) {
538 rtcp::Pli* pli = new rtcp::Pli();
539 pli->From(ssrc_);
540 pli->To(remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200541
Erik Språng242e22b2015-05-11 10:17:43 +0200542 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
543 "RTCPSender::PLI");
544 ++packet_type_counter_.pli_packets;
545 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
546 ssrc_, packet_type_counter_.pli_packets);
547
Erik Språngf7c57762015-12-04 10:40:35 +0100548 return rtc::scoped_ptr<rtcp::Pli>(pli);
Erik Språng61be2a42015-04-27 13:32:52 +0200549}
550
Erik Språngf7c57762015-12-04 10:40:35 +0100551rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildFIR(const RtcpContext& ctx) {
552 if (!ctx.repeat_)
sprang62dae192015-08-05 02:35:35 -0700553 ++sequence_number_fir_; // Do not increase if repetition.
niklase@google.com470e71d2011-07-07 08:21:25 +0000554
Erik Språngf7c57762015-12-04 10:40:35 +0100555 rtcp::Fir* fir = new rtcp::Fir();
556 fir->From(ssrc_);
557 fir->To(remote_ssrc_);
558 fir->WithCommandSeqNum(sequence_number_fir_);
Erik Språng242e22b2015-05-11 10:17:43 +0200559
560 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
561 "RTCPSender::FIR");
562 ++packet_type_counter_.fir_packets;
563 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
564 ssrc_, packet_type_counter_.fir_packets);
565
Erik Språngf7c57762015-12-04 10:40:35 +0100566 return rtc::scoped_ptr<rtcp::Fir>(fir);
niklase@google.com470e71d2011-07-07 08:21:25 +0000567}
568
569/*
570 0 1 2 3
571 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
572 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
573 | First | Number | PictureID |
574 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
575*/
Erik Språngf7c57762015-12-04 10:40:35 +0100576rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildSLI(const RtcpContext& ctx) {
577 rtcp::Sli* sli = new rtcp::Sli();
578 sli->From(ssrc_);
579 sli->To(remote_ssrc_);
sprang0365a272015-08-11 01:02:37 -0700580 // Crop picture id to 6 least significant bits.
Erik Språngf7c57762015-12-04 10:40:35 +0100581 sli->WithPictureId(ctx.picture_id_ & 0x3F);
582 sli->WithFirstMb(0);
583 sli->WithNumberOfMb(0x1FFF); // 13 bits, only ones for now.
sprang0365a272015-08-11 01:02:37 -0700584
Erik Språngf7c57762015-12-04 10:40:35 +0100585 return rtc::scoped_ptr<rtcp::Sli>(sli);
niklase@google.com470e71d2011-07-07 08:21:25 +0000586}
587
588/*
589 0 1 2 3
590 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
591 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
592 | PB |0| Payload Type| Native RPSI bit string |
593 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
594 | defined per codec ... | Padding (0) |
595 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
596*/
597/*
598* Note: not generic made for VP8
599*/
Erik Språngf7c57762015-12-04 10:40:35 +0100600rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildRPSI(
601 const RtcpContext& ctx) {
602 if (ctx.feedback_state_.send_payload_type == 0xFF)
603 return nullptr;
Erik Språng242e22b2015-05-11 10:17:43 +0200604
Erik Språngf7c57762015-12-04 10:40:35 +0100605 rtcp::Rpsi* rpsi = new rtcp::Rpsi();
606 rpsi->From(ssrc_);
607 rpsi->To(remote_ssrc_);
608 rpsi->WithPayloadType(ctx.feedback_state_.send_payload_type);
609 rpsi->WithPictureId(ctx.picture_id_);
sprangcf7f54d2015-08-13 04:37:42 -0700610
Erik Språngf7c57762015-12-04 10:40:35 +0100611 return rtc::scoped_ptr<rtcp::Rpsi>(rpsi);
niklase@google.com470e71d2011-07-07 08:21:25 +0000612}
613
Erik Språngf7c57762015-12-04 10:40:35 +0100614rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildREMB(
615 const RtcpContext& ctx) {
616 rtcp::Remb* remb = new rtcp::Remb();
617 remb->From(ssrc_);
sprangdd4edc52015-08-21 04:21:51 -0700618 for (uint32_t ssrc : remb_ssrcs_)
Erik Språngf7c57762015-12-04 10:40:35 +0100619 remb->AppliesTo(ssrc);
620 remb->WithBitrateBps(remb_bitrate_);
Erik Språng61be2a42015-04-27 13:32:52 +0200621
Erik Språng242e22b2015-05-11 10:17:43 +0200622 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
623 "RTCPSender::REMB");
624
Erik Språngf7c57762015-12-04 10:40:35 +0100625 return rtc::scoped_ptr<rtcp::Remb>(remb);
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000626}
627
Erik Språng61be2a42015-04-27 13:32:52 +0200628void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
Erik Språng242e22b2015-05-11 10:17:43 +0200629 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
630 tmmbr_send_ = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000631}
632
Erik Språngf7c57762015-12-04 10:40:35 +0100633rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBR(
634 const RtcpContext& ctx) {
635 if (ctx.feedback_state_.module == nullptr)
636 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200637 // Before sending the TMMBR check the received TMMBN, only an owner is
638 // allowed to raise the bitrate:
639 // * If the sender is an owner of the TMMBN -> send TMMBR
640 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000641
Erik Språng61be2a42015-04-27 13:32:52 +0200642 // get current bounding set from RTCP receiver
643 bool tmmbrOwner = false;
644 // store in candidateSet, allocates one extra slot
Erik Språng242e22b2015-05-11 10:17:43 +0200645 TMMBRSet* candidateSet = tmmbr_help_.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000646
Erik Språng242e22b2015-05-11 10:17:43 +0200647 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
648 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
Erik Språng61be2a42015-04-27 13:32:52 +0200649 // since RTCPreceiver is not doing the reverse we should be fine
650 int32_t lengthOfBoundingSet =
Erik Språngf7c57762015-12-04 10:40:35 +0100651 ctx.feedback_state_.module->BoundingSet(tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +0000652
Erik Språng61be2a42015-04-27 13:32:52 +0200653 if (lengthOfBoundingSet > 0) {
654 for (int32_t i = 0; i < lengthOfBoundingSet; i++) {
Erik Språng242e22b2015-05-11 10:17:43 +0200655 if (candidateSet->Tmmbr(i) == tmmbr_send_ &&
656 candidateSet->PacketOH(i) == packet_oh_send_) {
Erik Språngf7c57762015-12-04 10:40:35 +0100657 // Do not send the same tuple.
658 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200659 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000660 }
Erik Språng61be2a42015-04-27 13:32:52 +0200661 if (!tmmbrOwner) {
662 // use received bounding set as candidate set
663 // add current tuple
Erik Språng242e22b2015-05-11 10:17:43 +0200664 candidateSet->SetEntry(lengthOfBoundingSet, tmmbr_send_, packet_oh_send_,
665 ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200666 int numCandidates = lengthOfBoundingSet + 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000667
Erik Språng61be2a42015-04-27 13:32:52 +0200668 // find bounding set
Erik Språngf7c57762015-12-04 10:40:35 +0100669 TMMBRSet* boundingSet = nullptr;
Erik Språng242e22b2015-05-11 10:17:43 +0200670 int numBoundingSet = tmmbr_help_.FindTMMBRBoundingSet(boundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200671 if (numBoundingSet > 0 || numBoundingSet <= numCandidates)
Erik Språng242e22b2015-05-11 10:17:43 +0200672 tmmbrOwner = tmmbr_help_.IsOwner(ssrc_, numBoundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200673 if (!tmmbrOwner) {
Erik Språngf7c57762015-12-04 10:40:35 +0100674 // Did not enter bounding set, no meaning to send this request.
675 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200676 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000677 }
Erik Språng61be2a42015-04-27 13:32:52 +0200678 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000679
Erik Språngf7c57762015-12-04 10:40:35 +0100680 if (!tmmbr_send_)
681 return nullptr;
sprang81a3e602015-08-21 05:30:11 -0700682
Erik Språngf7c57762015-12-04 10:40:35 +0100683 rtcp::Tmmbr* tmmbr = new rtcp::Tmmbr();
684 tmmbr->From(ssrc_);
685 tmmbr->To(remote_ssrc_);
686 tmmbr->WithBitrateKbps(tmmbr_send_);
687 tmmbr->WithOverhead(packet_oh_send_);
688
689 return rtc::scoped_ptr<rtcp::Tmmbr>(tmmbr);
Erik Språng61be2a42015-04-27 13:32:52 +0200690}
691
Erik Språngf7c57762015-12-04 10:40:35 +0100692rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBN(
693 const RtcpContext& ctx) {
Erik Språng242e22b2015-05-11 10:17:43 +0200694 TMMBRSet* boundingSet = tmmbr_help_.BoundingSetToSend();
Erik Språngf7c57762015-12-04 10:40:35 +0100695 if (boundingSet == nullptr)
696 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200697
Erik Språngf7c57762015-12-04 10:40:35 +0100698 rtcp::Tmmbn* tmmbn = new rtcp::Tmmbn();
699 tmmbn->From(ssrc_);
sprangd83df502015-08-27 01:05:08 -0700700 for (uint32_t i = 0; i < boundingSet->lengthOfSet(); i++) {
701 if (boundingSet->Tmmbr(i) > 0) {
Erik Språngf7c57762015-12-04 10:40:35 +0100702 tmmbn->WithTmmbr(boundingSet->Ssrc(i), boundingSet->Tmmbr(i),
703 boundingSet->PacketOH(i));
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000704 }
Erik Språng61be2a42015-04-27 13:32:52 +0200705 }
sprangd83df502015-08-27 01:05:08 -0700706
Erik Språngf7c57762015-12-04 10:40:35 +0100707 return rtc::scoped_ptr<rtcp::Tmmbn>(tmmbn);
niklase@google.com470e71d2011-07-07 08:21:25 +0000708}
709
Erik Språngf7c57762015-12-04 10:40:35 +0100710rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildAPP(const RtcpContext& ctx) {
711 rtcp::App* app = new rtcp::App();
712 app->From(ssrc_);
713 app->WithSubType(app_sub_type_);
714 app->WithName(app_name_);
715 app->WithData(app_data_.get(), app_length_);
Erik Språng521875a2015-09-01 10:11:16 +0200716
Erik Språngf7c57762015-12-04 10:40:35 +0100717 return rtc::scoped_ptr<rtcp::App>(app);
Erik Språng61be2a42015-04-27 13:32:52 +0200718}
719
Erik Språngf7c57762015-12-04 10:40:35 +0100720rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildNACK(
721 const RtcpContext& ctx) {
722 rtcp::Nack* nack = new rtcp::Nack();
723 nack->From(ssrc_);
724 nack->To(remote_ssrc_);
725 nack->WithList(ctx.nack_list_, ctx.nack_size_);
Erik Språng61be2a42015-04-27 13:32:52 +0200726
727 // Report stats.
728 NACKStringBuilder stringBuilder;
Erik Språngf7c57762015-12-04 10:40:35 +0100729 for (int idx = 0; idx < ctx.nack_size_; ++idx) {
730 stringBuilder.PushNACK(ctx.nack_list_[idx]);
731 nack_stats_.ReportRequest(ctx.nack_list_[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +0200732 }
Erik Språng61be2a42015-04-27 13:32:52 +0200733 packet_type_counter_.nack_requests = nack_stats_.requests();
734 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +0200735
736 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
737 "RTCPSender::NACK", "nacks",
738 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
739 ++packet_type_counter_.nack_packets;
740 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
741 ssrc_, packet_type_counter_.nack_packets);
742
Erik Språngf7c57762015-12-04 10:40:35 +0100743 return rtc::scoped_ptr<rtcp::Nack>(nack);
Erik Språng61be2a42015-04-27 13:32:52 +0200744}
745
Erik Språngf7c57762015-12-04 10:40:35 +0100746rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildBYE(const RtcpContext& ctx) {
747 rtcp::Bye* bye = new rtcp::Bye();
748 bye->From(ssrc_);
sprangd8ee4f92015-08-24 03:25:19 -0700749 for (uint32_t csrc : csrcs_)
Erik Språngf7c57762015-12-04 10:40:35 +0100750 bye->WithCsrc(csrc);
sprangd8ee4f92015-08-24 03:25:19 -0700751
Erik Språngf7c57762015-12-04 10:40:35 +0100752 return rtc::scoped_ptr<rtcp::Bye>(bye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000753}
754
Erik Språngf7c57762015-12-04 10:40:35 +0100755rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildReceiverReferenceTime(
756 const RtcpContext& ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200757 if (last_xr_rr_.size() >= RTCP_NUMBER_OF_SR)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000758 last_xr_rr_.erase(last_xr_rr_.begin());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000759 last_xr_rr_.insert(std::pair<uint32_t, int64_t>(
Erik Språngf7c57762015-12-04 10:40:35 +0100760 RTCPUtility::MidNtp(ctx.ntp_sec_, ctx.ntp_frac_),
761 Clock::NtpToMs(ctx.ntp_sec_, ctx.ntp_frac_)));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000762
Erik Språngf7c57762015-12-04 10:40:35 +0100763 rtcp::Xr* xr = new rtcp::Xr();
764 xr->From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000765
Erik Språngca28fdc2015-08-31 14:00:50 +0200766 rtcp::Rrtr rrtr;
Erik Språngf7c57762015-12-04 10:40:35 +0100767 rrtr.WithNtpSec(ctx.ntp_sec_);
768 rrtr.WithNtpFrac(ctx.ntp_frac_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000769
Erik Språngf7c57762015-12-04 10:40:35 +0100770 xr->WithRrtr(&rrtr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000771
Erik Språngca28fdc2015-08-31 14:00:50 +0200772 // TODO(sprang): Merge XR report sending to contain all of RRTR, DLRR, VOIP?
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000773
Erik Språngf7c57762015-12-04 10:40:35 +0100774 return rtc::scoped_ptr<rtcp::Xr>(xr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000775}
776
Erik Språngf7c57762015-12-04 10:40:35 +0100777rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildDlrr(
778 const RtcpContext& ctx) {
779 rtcp::Xr* xr = new rtcp::Xr();
780 xr->From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000781
Erik Språngca28fdc2015-08-31 14:00:50 +0200782 rtcp::Dlrr dlrr;
Erik Språngf7c57762015-12-04 10:40:35 +0100783 const RtcpReceiveTimeInfo& info = ctx.feedback_state_.last_xr_rr;
Erik Språngca28fdc2015-08-31 14:00:50 +0200784 dlrr.WithDlrrItem(info.sourceSSRC, info.lastRR, info.delaySinceLastRR);
785
Erik Språngf7c57762015-12-04 10:40:35 +0100786 xr->WithDlrr(&dlrr);
Erik Språngca28fdc2015-08-31 14:00:50 +0200787
Erik Språngf7c57762015-12-04 10:40:35 +0100788 return rtc::scoped_ptr<rtcp::Xr>(xr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000789}
790
Erik Språng242e22b2015-05-11 10:17:43 +0200791// TODO(sprang): Add a unit test for this, or remove if the code isn't used.
Erik Språngf7c57762015-12-04 10:40:35 +0100792rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildVoIPMetric(
793 const RtcpContext& context) {
794 rtcp::Xr* xr = new rtcp::Xr();
795 xr->From(ssrc_);
Erik Språngca28fdc2015-08-31 14:00:50 +0200796
797 rtcp::VoipMetric voip;
798 voip.To(remote_ssrc_);
799 voip.LossRate(xr_voip_metric_.lossRate);
800 voip.DiscardRate(xr_voip_metric_.discardRate);
801 voip.BurstDensity(xr_voip_metric_.burstDensity);
802 voip.GapDensity(xr_voip_metric_.gapDensity);
803 voip.BurstDuration(xr_voip_metric_.burstDuration);
804 voip.GapDuration(xr_voip_metric_.gapDuration);
805 voip.RoundTripDelay(xr_voip_metric_.roundTripDelay);
806 voip.EndSystemDelay(xr_voip_metric_.endSystemDelay);
807 voip.SignalLevel(xr_voip_metric_.signalLevel);
808 voip.NoiseLevel(xr_voip_metric_.noiseLevel);
809 voip.Rerl(xr_voip_metric_.RERL);
810 voip.Gmin(xr_voip_metric_.Gmin);
811 voip.Rfactor(xr_voip_metric_.Rfactor);
812 voip.ExtRfactor(xr_voip_metric_.extRfactor);
813 voip.MosLq(xr_voip_metric_.MOSLQ);
814 voip.MosCq(xr_voip_metric_.MOSCQ);
815 voip.RxConfig(xr_voip_metric_.RXconfig);
816 voip.JbNominal(xr_voip_metric_.JBnominal);
817 voip.JbMax(xr_voip_metric_.JBmax);
818 voip.JbAbsMax(xr_voip_metric_.JBabsMax);
819
Erik Språngf7c57762015-12-04 10:40:35 +0100820 xr->WithVoipMetric(&voip);
Erik Språngca28fdc2015-08-31 14:00:50 +0200821
Erik Språngf7c57762015-12-04 10:40:35 +0100822 return rtc::scoped_ptr<rtcp::Xr>(xr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000823}
824
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000825int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200826 RTCPPacketType packetType,
827 int32_t nack_size,
828 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000829 bool repeat,
830 uint64_t pictureID) {
Erik Språng242e22b2015-05-11 10:17:43 +0200831 return SendCompoundRTCP(
832 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
833 nack_size, nack_list, repeat, pictureID);
834}
835
836int32_t RTCPSender::SendCompoundRTCP(
837 const FeedbackState& feedback_state,
Erik Språngf7c57762015-12-04 10:40:35 +0100838 const std::set<RTCPPacketType>& packet_types,
Erik Språng242e22b2015-05-11 10:17:43 +0200839 int32_t nack_size,
840 const uint16_t* nack_list,
841 bool repeat,
842 uint64_t pictureID) {
Erik Språngf7c57762015-12-04 10:40:35 +0100843 PacketContainer container(transport_);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000844 {
Erik Språng242e22b2015-05-11 10:17:43 +0200845 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
pbosda903ea2015-10-02 02:36:56 -0700846 if (method_ == RtcpMode::kOff) {
Erik Språng61be2a42015-04-27 13:32:52 +0200847 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
848 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +0000849 }
Erik Språngf7c57762015-12-04 10:40:35 +0100850
851 // We need to send our NTP even if we haven't received any reports.
852 uint32_t ntp_sec;
853 uint32_t ntp_frac;
854 clock_->CurrentNtp(ntp_sec, ntp_frac);
855 RtcpContext context(feedback_state, nack_size, nack_list, repeat, pictureID,
856 ntp_sec, ntp_frac, &container);
857
858 PrepareReport(packet_types, feedback_state);
859
860 auto it = report_flags_.begin();
861 while (it != report_flags_.end()) {
862 auto builder_it = builders_.find(it->type);
863 RTC_DCHECK(builder_it != builders_.end());
864 if (it->is_volatile) {
865 report_flags_.erase(it++);
866 } else {
867 ++it;
868 }
869
870 BuilderFunc func = builder_it->second;
871 rtc::scoped_ptr<rtcp::RtcpPacket> packet = (this->*func)(context);
872 if (packet.get() == nullptr)
873 return -1;
874 container.Append(packet.release());
875 }
876
877 if (packet_type_counter_observer_ != nullptr) {
878 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
879 remote_ssrc_, packet_type_counter_);
880 }
881
882 RTC_DCHECK(AllVolatileFlagsConsumed());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000883 }
Erik Språng61be2a42015-04-27 13:32:52 +0200884
Erik Språngf7c57762015-12-04 10:40:35 +0100885 size_t bytes_sent = container.SendPackets();
886 return bytes_sent == 0 ? -1 : 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000887}
888
Erik Språngf7c57762015-12-04 10:40:35 +0100889void RTCPSender::PrepareReport(const std::set<RTCPPacketType>& packetTypes,
890 const FeedbackState& feedback_state) {
Erik Språng242e22b2015-05-11 10:17:43 +0200891 // Add all flags as volatile. Non volatile entries will not be overwritten
892 // and all new volatile flags added will be consumed by the end of this call.
893 SetFlags(packetTypes, true);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000894
Erik Språng61be2a42015-04-27 13:32:52 +0200895 if (packet_type_counter_.first_packet_time_ms == -1)
Erik Språng242e22b2015-05-11 10:17:43 +0200896 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språng61be2a42015-04-27 13:32:52 +0200897
Erik Språng242e22b2015-05-11 10:17:43 +0200898 bool generate_report;
899 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
900 // Report type already explicitly set, don't automatically populate.
901 generate_report = true;
henrikg91d6ede2015-09-17 00:24:34 -0700902 RTC_DCHECK(ConsumeFlag(kRtcpReport) == false);
Erik Språng242e22b2015-05-11 10:17:43 +0200903 } else {
904 generate_report =
pbosda903ea2015-10-02 02:36:56 -0700905 (ConsumeFlag(kRtcpReport) && method_ == RtcpMode::kReducedSize) ||
906 method_ == RtcpMode::kCompound;
Erik Språng242e22b2015-05-11 10:17:43 +0200907 if (generate_report)
908 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000909 }
910
Erik Språng0ea42d32015-06-25 14:46:16 +0200911 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
Erik Språng242e22b2015-05-11 10:17:43 +0200912 SetFlag(kRtcpSdes, true);
913
Erik Språng242e22b2015-05-11 10:17:43 +0200914 if (generate_report) {
915 if (!sending_ && xr_send_receiver_reference_time_enabled_)
916 SetFlag(kRtcpXrReceiverReferenceTime, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200917 if (feedback_state.has_last_xr_rr)
Erik Språng242e22b2015-05-11 10:17:43 +0200918 SetFlag(kRtcpXrDlrrReportBlock, true);
919
920 // generate next time to send an RTCP report
Erik Språng61be2a42015-04-27 13:32:52 +0200921 // seeded from RTP constructor
922 int32_t random = rand() % 1000;
923 int32_t timeToNext = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000924
Erik Språng242e22b2015-05-11 10:17:43 +0200925 if (audio_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200926 timeToNext = (RTCP_INTERVAL_AUDIO_MS / 2) +
927 (RTCP_INTERVAL_AUDIO_MS * random / 1000);
928 } else {
929 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
Erik Språng242e22b2015-05-11 10:17:43 +0200930 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200931 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
932 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
933 if (send_bitrate_kbit != 0)
934 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000935 }
Erik Språng61be2a42015-04-27 13:32:52 +0200936 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
937 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
938 timeToNext = (minIntervalMs / 2) + (minIntervalMs * random / 1000);
939 }
Erik Språng242e22b2015-05-11 10:17:43 +0200940 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000941
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000942 StatisticianMap statisticians =
943 receive_statistics_->GetActiveStatisticians();
944 if (!statisticians.empty()) {
Erik Språng61be2a42015-04-27 13:32:52 +0200945 for (auto it = statisticians.begin(); it != statisticians.end(); ++it) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000946 RTCPReportBlock report_block;
Erik Språngf7c57762015-12-04 10:40:35 +0100947 if (PrepareReportBlock(feedback_state, it->first, it->second,
948 &report_block)) {
danilchapdf948f02015-11-13 03:03:13 -0800949 // TODO(danilchap) AddReportBlock may fail (for 2 different reasons).
950 // Probably it shouldn't be ignored.
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200951 AddReportBlock(report_block);
Erik Språng61be2a42015-04-27 13:32:52 +0200952 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000953 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000954 }
955 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000956}
957
Erik Språngf7c57762015-12-04 10:40:35 +0100958bool RTCPSender::PrepareReportBlock(const FeedbackState& feedback_state,
959 uint32_t ssrc,
960 StreamStatistician* statistician,
961 RTCPReportBlock* report_block) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000962 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000963 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000964 if (!statistician->GetStatistics(&stats, true))
965 return false;
966 report_block->fractionLost = stats.fraction_lost;
967 report_block->cumulativeLost = stats.cumulative_lost;
968 report_block->extendedHighSeqNum =
969 stats.extended_max_sequence_number;
970 report_block->jitter = stats.jitter;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200971 report_block->remoteSSRC = ssrc;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000972
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200973 // TODO(sprang): Do we really need separate time stamps for each report?
974 // Get our NTP as late as possible to avoid a race.
975 uint32_t ntp_secs;
976 uint32_t ntp_frac;
977 clock_->CurrentNtp(ntp_secs, ntp_frac);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000978
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200979 // Delay since last received report.
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000980 uint32_t delaySinceLastReceivedSR = 0;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000981 if ((feedback_state.last_rr_ntp_secs != 0) ||
982 (feedback_state.last_rr_ntp_frac != 0)) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200983 // Get the 16 lowest bits of seconds and the 16 highest bits of fractions.
984 uint32_t now = ntp_secs & 0x0000FFFF;
Erik Språng61be2a42015-04-27 13:32:52 +0200985 now <<= 16;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200986 now += (ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000987
Erik Språng61be2a42015-04-27 13:32:52 +0200988 uint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
989 receiveTime <<= 16;
990 receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000991
992 delaySinceLastReceivedSR = now-receiveTime;
993 }
994 report_block->delaySinceLastSR = delaySinceLastReceivedSR;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000995 report_block->lastSR = feedback_state.remote_sr;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000996 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000997}
998
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000999void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
1000 assert(csrcs.size() <= kRtpCsrcSize);
Erik Språng242e22b2015-05-11 10:17:43 +02001001 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001002 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +00001003}
1004
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001005int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
1006 uint32_t name,
1007 const uint8_t* data,
1008 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +02001009 if (length % 4 != 0) {
1010 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
1011 return -1;
1012 }
Erik Språng242e22b2015-05-11 10:17:43 +02001013 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +00001014
Erik Språng242e22b2015-05-11 10:17:43 +02001015 SetFlag(kRtcpApp, true);
1016 app_sub_type_ = subType;
1017 app_name_ = name;
1018 app_data_.reset(new uint8_t[length]);
1019 app_length_ = length;
1020 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +02001021 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001022}
1023
Erik Språng61be2a42015-04-27 13:32:52 +02001024int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
Erik Språng242e22b2015-05-11 10:17:43 +02001025 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1026 memcpy(&xr_voip_metric_, VoIPMetric, sizeof(RTCPVoIPMetric));
niklase@google.com470e71d2011-07-07 08:21:25 +00001027
Erik Språng242e22b2015-05-11 10:17:43 +02001028 SetFlag(kRtcpXrVoipMetric, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001029 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001030}
1031
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001032void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +02001033 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1034 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001035}
1036
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00001037bool RTCPSender::RtcpXrReceiverReferenceTime() const {
Erik Språng242e22b2015-05-11 10:17:43 +02001038 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1039 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00001040}
1041
niklase@google.com470e71d2011-07-07 08:21:25 +00001042// no callbacks allowed inside this function
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001043int32_t RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
1044 uint32_t maxBitrateKbit) {
Erik Språng242e22b2015-05-11 10:17:43 +02001045 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +00001046
Erik Språng242e22b2015-05-11 10:17:43 +02001047 if (0 == tmmbr_help_.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit)) {
1048 SetFlag(kRtcpTmmbn, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001049 return 0;
1050 }
1051 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001052}
Erik Språng61be2a42015-04-27 13:32:52 +02001053
Erik Språng242e22b2015-05-11 10:17:43 +02001054void RTCPSender::SetFlag(RTCPPacketType type, bool is_volatile) {
1055 report_flags_.insert(ReportFlag(type, is_volatile));
1056}
1057
1058void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
1059 bool is_volatile) {
1060 for (RTCPPacketType type : types)
1061 SetFlag(type, is_volatile);
1062}
1063
1064bool RTCPSender::IsFlagPresent(RTCPPacketType type) const {
1065 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
1066}
1067
1068bool RTCPSender::ConsumeFlag(RTCPPacketType type, bool forced) {
1069 auto it = report_flags_.find(ReportFlag(type, false));
1070 if (it == report_flags_.end())
1071 return false;
1072 if (it->is_volatile || forced)
1073 report_flags_.erase((it));
1074 return true;
1075}
1076
1077bool RTCPSender::AllVolatileFlagsConsumed() const {
1078 for (const ReportFlag& flag : report_flags_) {
1079 if (flag.is_volatile)
1080 return false;
1081 }
1082 return true;
1083}
1084
sprang233bd872015-09-08 13:25:16 -07001085bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
sprang233bd872015-09-08 13:25:16 -07001086 class Sender : public rtcp::RtcpPacket::PacketReadyCallback {
1087 public:
Peter Boströmac547a62015-09-17 23:03:57 +02001088 Sender(Transport* transport)
1089 : transport_(transport), send_failure_(false) {}
sprang233bd872015-09-08 13:25:16 -07001090
1091 void OnPacketReady(uint8_t* data, size_t length) override {
pbos2d566682015-09-28 09:59:31 -07001092 if (!transport_->SendRtcp(data, length))
sprang233bd872015-09-08 13:25:16 -07001093 send_failure_ = true;
1094 }
1095
1096 Transport* const transport_;
sprang233bd872015-09-08 13:25:16 -07001097 bool send_failure_;
sprang86fd9ed2015-09-29 04:45:43 -07001098 } sender(transport_);
sprang233bd872015-09-08 13:25:16 -07001099
1100 uint8_t buffer[IP_PACKET_SIZE];
1101 return packet.BuildExternalBuffer(buffer, IP_PACKET_SIZE, &sender) &&
1102 !sender.send_failure_;
1103}
1104
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001105} // namespace webrtc