blob: ddf24ab786b1a78b557c87e53f4fe818791d67cf [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
danilchapb8b6fbb2015-12-10 05:05:27 -080019#include <utility>
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000020
Erik Språng61be2a42015-04-27 13:32:52 +020021#include "webrtc/base/checks.h"
Peter Boströmebc0b4e2015-10-28 16:39:33 +010022#include "webrtc/base/logging.h"
tommie4f96502015-10-20 23:00:48 -070023#include "webrtc/base/trace_event.h"
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000024#include "webrtc/common_types.h"
sprang@webrtc.org779c3d12015-03-17 16:42:49 +000025#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
danilchap0219c9b2015-11-18 05:56:53 -080026#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/app.h"
danilchap50c51362015-11-22 09:03:11 -080027#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/bye.h"
danilchapf8385ad2015-11-27 05:36:09 -080028#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/pli.h"
Danil Chapovalov97f7e132015-12-04 16:13:30 +010029#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
sprang233bd872015-09-08 13:25:16 -070030#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
tommie4f96502015-10-20 23:00:48 -070031#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010032#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000033
niklase@google.com470e71d2011-07-07 08:21:25 +000034namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000035
36using RTCPUtility::RTCPCnameInformation;
37
Erik Språng61be2a42015-04-27 13:32:52 +020038NACKStringBuilder::NACKStringBuilder()
danilchap162abd32015-12-10 02:39:40 -080039 : stream_(""), count_(0), prevNack_(0), consecutive_(false) {}
edjee@google.com79b02892013-04-04 19:43:34 +000040
pbos@webrtc.orgf3e4cee2013-07-31 15:17:19 +000041NACKStringBuilder::~NACKStringBuilder() {}
42
danilchap162abd32015-12-10 02:39:40 -080043void NACKStringBuilder::PushNACK(uint16_t nack) {
Erik Språng242e22b2015-05-11 10:17:43 +020044 if (count_ == 0) {
45 stream_ << nack;
46 } else if (nack == prevNack_ + 1) {
47 consecutive_ = true;
Erik Språng61be2a42015-04-27 13:32:52 +020048 } else {
Erik Språng242e22b2015-05-11 10:17:43 +020049 if (consecutive_) {
50 stream_ << "-" << prevNack_;
51 consecutive_ = false;
edjee@google.com79b02892013-04-04 19:43:34 +000052 }
Erik Språng242e22b2015-05-11 10:17:43 +020053 stream_ << "," << nack;
Erik Språng61be2a42015-04-27 13:32:52 +020054 }
Erik Språng242e22b2015-05-11 10:17:43 +020055 count_++;
56 prevNack_ = nack;
edjee@google.com79b02892013-04-04 19:43:34 +000057}
58
Erik Språng61be2a42015-04-27 13:32:52 +020059std::string NACKStringBuilder::GetResult() {
Erik Språng242e22b2015-05-11 10:17:43 +020060 if (consecutive_) {
61 stream_ << "-" << prevNack_;
62 consecutive_ = false;
Erik Språng61be2a42015-04-27 13:32:52 +020063 }
Erik Språng242e22b2015-05-11 10:17:43 +020064 return stream_.str();
edjee@google.com79b02892013-04-04 19:43:34 +000065}
66
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000067RTCPSender::FeedbackState::FeedbackState()
68 : send_payload_type(0),
69 frequency_hz(0),
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +000070 packets_sent(0),
71 media_bytes_sent(0),
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000072 send_bitrate(0),
73 last_rr_ntp_secs(0),
74 last_rr_ntp_frac(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000075 remote_sr(0),
Erik Språng61be2a42015-04-27 13:32:52 +020076 has_last_xr_rr(false),
danilchap162abd32015-12-10 02:39:40 -080077 module(nullptr) {}
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000078
Erik Språngf7c57762015-12-04 10:40:35 +010079class PacketContainer : public rtcp::Empty,
80 public rtcp::RtcpPacket::PacketReadyCallback {
81 public:
82 explicit PacketContainer(Transport* transport)
83 : transport_(transport), bytes_sent_(0) {}
84 virtual ~PacketContainer() {
85 for (RtcpPacket* packet : appended_packets_)
86 delete packet;
87 }
88
89 void OnPacketReady(uint8_t* data, size_t length) override {
90 if (transport_->SendRtcp(data, length))
91 bytes_sent_ += length;
92 }
93
94 size_t SendPackets() {
95 rtcp::Empty::Build(this);
96 return bytes_sent_;
97 }
98
99 private:
100 Transport* transport_;
101 size_t bytes_sent_;
102};
103
104class RTCPSender::RtcpContext {
105 public:
Erik Språng242e22b2015-05-11 10:17:43 +0200106 RtcpContext(const FeedbackState& feedback_state,
107 int32_t nack_size,
108 const uint16_t* nack_list,
109 bool repeat,
110 uint64_t picture_id,
Erik Språngf7c57762015-12-04 10:40:35 +0100111 uint32_t ntp_sec,
112 uint32_t ntp_frac,
113 PacketContainer* container)
114 : feedback_state_(feedback_state),
115 nack_size_(nack_size),
116 nack_list_(nack_list),
117 repeat_(repeat),
118 picture_id_(picture_id),
119 ntp_sec_(ntp_sec),
120 ntp_frac_(ntp_frac),
121 container_(container) {}
Erik Språng242e22b2015-05-11 10:17:43 +0200122
Erik Språngf7c57762015-12-04 10:40:35 +0100123 virtual ~RtcpContext() {}
Erik Språng242e22b2015-05-11 10:17:43 +0200124
Erik Språngf7c57762015-12-04 10:40:35 +0100125 const FeedbackState& feedback_state_;
126 const int32_t nack_size_;
127 const uint16_t* nack_list_;
128 const bool repeat_;
129 const uint64_t picture_id_;
130 const uint32_t ntp_sec_;
131 const uint32_t ntp_frac_;
Erik Språng242e22b2015-05-11 10:17:43 +0200132
Erik Språngf7c57762015-12-04 10:40:35 +0100133 PacketContainer* const container_;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200134};
135
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000136RTCPSender::RTCPSender(
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000137 bool audio,
138 Clock* clock,
139 ReceiveStatistics* receive_statistics,
sprang86fd9ed2015-09-29 04:45:43 -0700140 RtcpPacketTypeCounterObserver* packet_type_counter_observer,
141 Transport* outgoing_transport)
Peter Boströmac547a62015-09-17 23:03:57 +0200142 : audio_(audio),
Erik Språng242e22b2015-05-11 10:17:43 +0200143 clock_(clock),
pbosda903ea2015-10-02 02:36:56 -0700144 method_(RtcpMode::kOff),
sprang86fd9ed2015-09-29 04:45:43 -0700145 transport_(outgoing_transport),
niklase@google.com470e71d2011-07-07 08:21:25 +0000146
Erik Språng242e22b2015-05-11 10:17:43 +0200147 critical_section_rtcp_sender_(
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000148 CriticalSectionWrapper::CreateCriticalSection()),
Erik Språng242e22b2015-05-11 10:17:43 +0200149 using_nack_(false),
150 sending_(false),
151 remb_enabled_(false),
Erik Språng242e22b2015-05-11 10:17:43 +0200152 next_time_to_send_rtcp_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000153 start_timestamp_(0),
154 last_rtp_timestamp_(0),
155 last_frame_capture_time_ms_(-1),
Erik Språng242e22b2015-05-11 10:17:43 +0200156 ssrc_(0),
157 remote_ssrc_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000158 receive_statistics_(receive_statistics),
niklase@google.com470e71d2011-07-07 08:21:25 +0000159
Erik Språng242e22b2015-05-11 10:17:43 +0200160 sequence_number_fir_(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000161
Erik Språng242e22b2015-05-11 10:17:43 +0200162 remb_bitrate_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000163
Erik Språng242e22b2015-05-11 10:17:43 +0200164 tmmbr_help_(),
165 tmmbr_send_(0),
166 packet_oh_send_(0),
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000167
Erik Språng242e22b2015-05-11 10:17:43 +0200168 app_sub_type_(0),
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200169 app_name_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200170 app_data_(nullptr),
171 app_length_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000172
Erik Språng242e22b2015-05-11 10:17:43 +0200173 xr_send_receiver_reference_time_enabled_(false),
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000174 packet_type_counter_observer_(packet_type_counter_observer) {
Erik Språng242e22b2015-05-11 10:17:43 +0200175 memset(last_send_report_, 0, sizeof(last_send_report_));
176 memset(last_rtcp_time_, 0, sizeof(last_rtcp_time_));
sprang86fd9ed2015-09-29 04:45:43 -0700177 RTC_DCHECK(transport_ != nullptr);
Erik Språng242e22b2015-05-11 10:17:43 +0200178
179 builders_[kRtcpSr] = &RTCPSender::BuildSR;
180 builders_[kRtcpRr] = &RTCPSender::BuildRR;
Erik Språng0ea42d32015-06-25 14:46:16 +0200181 builders_[kRtcpSdes] = &RTCPSender::BuildSDES;
Erik Språng242e22b2015-05-11 10:17:43 +0200182 builders_[kRtcpPli] = &RTCPSender::BuildPLI;
183 builders_[kRtcpFir] = &RTCPSender::BuildFIR;
184 builders_[kRtcpSli] = &RTCPSender::BuildSLI;
185 builders_[kRtcpRpsi] = &RTCPSender::BuildRPSI;
186 builders_[kRtcpRemb] = &RTCPSender::BuildREMB;
187 builders_[kRtcpBye] = &RTCPSender::BuildBYE;
188 builders_[kRtcpApp] = &RTCPSender::BuildAPP;
189 builders_[kRtcpTmmbr] = &RTCPSender::BuildTMMBR;
190 builders_[kRtcpTmmbn] = &RTCPSender::BuildTMMBN;
191 builders_[kRtcpNack] = &RTCPSender::BuildNACK;
192 builders_[kRtcpXrVoipMetric] = &RTCPSender::BuildVoIPMetric;
193 builders_[kRtcpXrReceiverReferenceTime] =
194 &RTCPSender::BuildReceiverReferenceTime;
195 builders_[kRtcpXrDlrrReportBlock] = &RTCPSender::BuildDlrr;
niklase@google.com470e71d2011-07-07 08:21:25 +0000196}
197
danilchap162abd32015-12-10 02:39:40 -0800198RTCPSender::~RTCPSender() {}
niklase@google.com470e71d2011-07-07 08:21:25 +0000199
pbosda903ea2015-10-02 02:36:56 -0700200RtcpMode RTCPSender::Status() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200201 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
202 return method_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000203}
204
pbosda903ea2015-10-02 02:36:56 -0700205void RTCPSender::SetRTCPStatus(RtcpMode method) {
Erik Språng242e22b2015-05-11 10:17:43 +0200206 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
207 method_ = method;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000208
pbosda903ea2015-10-02 02:36:56 -0700209 if (method == RtcpMode::kOff)
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000210 return;
Erik Språng242e22b2015-05-11 10:17:43 +0200211 next_time_to_send_rtcp_ =
212 clock_->TimeInMilliseconds() +
213 (audio_ ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000214}
215
Erik Språng61be2a42015-04-27 13:32:52 +0200216bool RTCPSender::Sending() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200217 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
218 return sending_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000219}
220
Erik Språng61be2a42015-04-27 13:32:52 +0200221int32_t RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
222 bool sending) {
223 bool sendRTCPBye = false;
224 {
Erik Språng242e22b2015-05-11 10:17:43 +0200225 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000226
pbosda903ea2015-10-02 02:36:56 -0700227 if (method_ != RtcpMode::kOff) {
Erik Språng242e22b2015-05-11 10:17:43 +0200228 if (sending == false && sending_ == true) {
Erik Språng61be2a42015-04-27 13:32:52 +0200229 // Trigger RTCP bye
230 sendRTCPBye = true;
231 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000232 }
Erik Språng242e22b2015-05-11 10:17:43 +0200233 sending_ = sending;
Erik Språng61be2a42015-04-27 13:32:52 +0200234 }
235 if (sendRTCPBye)
236 return SendRTCP(feedback_state, kRtcpBye);
237 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000238}
239
Erik Språng61be2a42015-04-27 13:32:52 +0200240bool RTCPSender::REMB() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200241 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
242 return remb_enabled_;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000243}
244
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000245void RTCPSender::SetREMBStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200246 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
247 remb_enabled_ = enable;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000248}
249
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000250void RTCPSender::SetREMBData(uint32_t bitrate,
251 const std::vector<uint32_t>& ssrcs) {
Erik Språng242e22b2015-05-11 10:17:43 +0200252 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
253 remb_bitrate_ = bitrate;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000254 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000255
Erik Språng242e22b2015-05-11 10:17:43 +0200256 if (remb_enabled_)
257 SetFlag(kRtcpRemb, false);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000258 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
259 // throttled by the caller.
Erik Språng242e22b2015-05-11 10:17:43 +0200260 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000261}
262
Erik Språng61be2a42015-04-27 13:32:52 +0200263bool RTCPSender::TMMBR() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200264 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
265 return IsFlagPresent(RTCPPacketType::kRtcpTmmbr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000266}
267
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000268void RTCPSender::SetTMMBRStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200269 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
270 if (enable) {
271 SetFlag(RTCPPacketType::kRtcpTmmbr, false);
272 } else {
273 ConsumeFlag(RTCPPacketType::kRtcpTmmbr, true);
274 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000275}
276
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000277void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
Erik Språng242e22b2015-05-11 10:17:43 +0200278 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000279 start_timestamp_ = start_timestamp;
280}
281
282void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
283 int64_t capture_time_ms) {
Erik Språng242e22b2015-05-11 10:17:43 +0200284 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000285 last_rtp_timestamp_ = rtp_timestamp;
286 if (capture_time_ms < 0) {
287 // We don't currently get a capture time from VoiceEngine.
Erik Språng242e22b2015-05-11 10:17:43 +0200288 last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000289 } else {
290 last_frame_capture_time_ms_ = capture_time_ms;
291 }
292}
293
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000294void RTCPSender::SetSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200295 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000296
Erik Språng242e22b2015-05-11 10:17:43 +0200297 if (ssrc_ != 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200298 // not first SetSSRC, probably due to a collision
299 // schedule a new RTCP report
300 // make sure that we send a RTP packet
Erik Språng242e22b2015-05-11 10:17:43 +0200301 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
Erik Språng61be2a42015-04-27 13:32:52 +0200302 }
Erik Språng242e22b2015-05-11 10:17:43 +0200303 ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000304}
305
Erik Språng61be2a42015-04-27 13:32:52 +0200306void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200307 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
308 remote_ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000309}
310
Peter Boström9ba52f82015-06-01 14:12:28 +0200311int32_t RTCPSender::SetCNAME(const char* c_name) {
312 if (!c_name)
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000313 return -1;
314
henrikg91d6ede2015-09-17 00:24:34 -0700315 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
Erik Språng242e22b2015-05-11 10:17:43 +0200316 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200317 cname_ = c_name;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000318 return 0;
319}
320
Erik Språng0ea42d32015-06-25 14:46:16 +0200321int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC, const char* c_name) {
322 assert(c_name);
henrikg91d6ede2015-09-17 00:24:34 -0700323 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
Erik Språng242e22b2015-05-11 10:17:43 +0200324 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200325 if (csrc_cnames_.size() >= kRtpCsrcSize)
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000326 return -1;
Erik Språng0ea42d32015-06-25 14:46:16 +0200327
328 csrc_cnames_[SSRC] = c_name;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000329 return 0;
330}
331
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000332int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
Erik Språng242e22b2015-05-11 10:17:43 +0200333 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200334 auto it = csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000335
Erik Språng242e22b2015-05-11 10:17:43 +0200336 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000337 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200338
Erik Språng242e22b2015-05-11 10:17:43 +0200339 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000340 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000341}
342
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000343bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
danilchap162abd32015-12-10 02:39:40 -0800344 /*
345 For audio we use a fix 5 sec interval
niklase@google.com470e71d2011-07-07 08:21:25 +0000346
danilchap162abd32015-12-10 02:39:40 -0800347 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
348 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
349 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000350
351
danilchap162abd32015-12-10 02:39:40 -0800352 From RFC 3550
niklase@google.com470e71d2011-07-07 08:21:25 +0000353
danilchap162abd32015-12-10 02:39:40 -0800354 MAX RTCP BW is 5% if the session BW
355 A send report is approximately 65 bytes inc CNAME
356 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000357
danilchap162abd32015-12-10 02:39:40 -0800358 The RECOMMENDED value for the reduced minimum in seconds is 360
359 divided by the session bandwidth in kilobits/second. This minimum
360 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
niklase@google.com470e71d2011-07-07 08:21:25 +0000361
danilchap162abd32015-12-10 02:39:40 -0800362 If the participant has not yet sent an RTCP packet (the variable
363 initial is true), the constant Tmin is set to 2.5 seconds, else it
364 is set to 5 seconds.
niklase@google.com470e71d2011-07-07 08:21:25 +0000365
danilchap162abd32015-12-10 02:39:40 -0800366 The interval between RTCP packets is varied randomly over the
367 range [0.5,1.5] times the calculated interval to avoid unintended
368 synchronization of all participants
niklase@google.com470e71d2011-07-07 08:21:25 +0000369
danilchap162abd32015-12-10 02:39:40 -0800370 if we send
371 If the participant is a sender (we_sent true), the constant C is
372 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
373 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
374 number of senders.
niklase@google.com470e71d2011-07-07 08:21:25 +0000375
danilchap162abd32015-12-10 02:39:40 -0800376 if we receive only
377 If we_sent is not true, the constant C is set
378 to the average RTCP packet size divided by 75% of the RTCP
379 bandwidth. The constant n is set to the number of receivers
380 (members - senders). If the number of senders is greater than
381 25%, senders and receivers are treated together.
niklase@google.com470e71d2011-07-07 08:21:25 +0000382
danilchap162abd32015-12-10 02:39:40 -0800383 reconsideration NOT required for peer-to-peer
384 "timer reconsideration" is
385 employed. This algorithm implements a simple back-off mechanism
386 which causes users to hold back RTCP packet transmission if the
387 group sizes are increasing.
niklase@google.com470e71d2011-07-07 08:21:25 +0000388
danilchap162abd32015-12-10 02:39:40 -0800389 n = number of members
390 C = avg_size/(rtcpBW/4)
niklase@google.com470e71d2011-07-07 08:21:25 +0000391
danilchap162abd32015-12-10 02:39:40 -0800392 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
niklase@google.com470e71d2011-07-07 08:21:25 +0000393
danilchap162abd32015-12-10 02:39:40 -0800394 4. The calculated interval T is set to a number uniformly distributed
395 between 0.5 and 1.5 times the deterministic calculated interval.
niklase@google.com470e71d2011-07-07 08:21:25 +0000396
danilchap162abd32015-12-10 02:39:40 -0800397 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
398 for the fact that the timer reconsideration algorithm converges to
399 a value of the RTCP bandwidth below the intended average
400 */
niklase@google.com470e71d2011-07-07 08:21:25 +0000401
Erik Språng242e22b2015-05-11 10:17:43 +0200402 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000403
Erik Språng242e22b2015-05-11 10:17:43 +0200404 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
xians@webrtc.org8738d272011-11-25 13:43:53 +0000405
pbosda903ea2015-10-02 02:36:56 -0700406 if (method_ == RtcpMode::kOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000407 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000408
Erik Språng242e22b2015-05-11 10:17:43 +0200409 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200410 // for video key-frames we want to send the RTCP before the large key-frame
411 // if we have a 100 ms margin
412 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
413 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000414
Erik Språng242e22b2015-05-11 10:17:43 +0200415 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200416 return true;
417 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200418 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200419 // wrap
420 return true;
421 }
422 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000423}
424
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000425int64_t RTCPSender::SendTimeOfSendReport(uint32_t sendReport) {
Erik Språng242e22b2015-05-11 10:17:43 +0200426 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000427
Erik Språng61be2a42015-04-27 13:32:52 +0200428 // This is only saved when we are the sender
Erik Språng242e22b2015-05-11 10:17:43 +0200429 if ((last_send_report_[0] == 0) || (sendReport == 0)) {
Erik Språng61be2a42015-04-27 13:32:52 +0200430 return 0; // will be ignored
431 } else {
432 for (int i = 0; i < RTCP_NUMBER_OF_SR; ++i) {
Erik Språng242e22b2015-05-11 10:17:43 +0200433 if (last_send_report_[i] == sendReport)
434 return last_rtcp_time_[i];
niklase@google.com470e71d2011-07-07 08:21:25 +0000435 }
Erik Språng61be2a42015-04-27 13:32:52 +0200436 }
437 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000438}
439
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000440bool RTCPSender::SendTimeOfXrRrReport(uint32_t mid_ntp,
441 int64_t* time_ms) const {
Erik Språng242e22b2015-05-11 10:17:43 +0200442 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000443
444 if (last_xr_rr_.empty()) {
445 return false;
446 }
447 std::map<uint32_t, int64_t>::const_iterator it = last_xr_rr_.find(mid_ntp);
448 if (it == last_xr_rr_.end()) {
449 return false;
450 }
451 *time_ms = it->second;
452 return true;
453}
454
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200455int32_t RTCPSender::AddReportBlock(const RTCPReportBlock& report_block) {
456 if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000457 LOG(LS_WARNING) << "Too many report blocks.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000458 return -1;
459 }
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200460 rtcp::ReportBlock* block = &report_blocks_[report_block.remoteSSRC];
461 block->To(report_block.remoteSSRC);
462 block->WithFractionLost(report_block.fractionLost);
danilchapdf948f02015-11-13 03:03:13 -0800463 if (!block->WithCumulativeLost(report_block.cumulativeLost)) {
464 LOG(LS_WARNING) << "Cumulative lost is oversized.";
465 return -1;
466 }
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200467 block->WithExtHighestSeqNum(report_block.extendedHighSeqNum);
468 block->WithJitter(report_block.jitter);
469 block->WithLastSr(report_block.lastSR);
470 block->WithDelayLastSr(report_block.delaySinceLastSR);
471
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000472 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000473}
474
Erik Språngf7c57762015-12-04 10:40:35 +0100475rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildSR(const RtcpContext& ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200476 for (int i = (RTCP_NUMBER_OF_SR - 2); i >= 0; i--) {
477 // shift old
Erik Språng242e22b2015-05-11 10:17:43 +0200478 last_send_report_[i + 1] = last_send_report_[i];
479 last_rtcp_time_[i + 1] = last_rtcp_time_[i];
Erik Språng61be2a42015-04-27 13:32:52 +0200480 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000481
Erik Språngf7c57762015-12-04 10:40:35 +0100482 last_rtcp_time_[0] = Clock::NtpToMs(ctx.ntp_sec_, ctx.ntp_frac_);
483 last_send_report_[0] = (ctx.ntp_sec_ << 16) + (ctx.ntp_frac_ >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000484
Erik Språng61be2a42015-04-27 13:32:52 +0200485 // The timestamp of this RTCP packet should be estimated as the timestamp of
486 // the frame being captured at this moment. We are calculating that
487 // timestamp as the last frame's timestamp + the time since the last frame
488 // was captured.
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200489 uint32_t rtp_timestamp =
490 start_timestamp_ + last_rtp_timestamp_ +
491 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) *
Erik Språngf7c57762015-12-04 10:40:35 +0100492 (ctx.feedback_state_.frequency_hz / 1000);
niklase@google.com470e71d2011-07-07 08:21:25 +0000493
Erik Språngf7c57762015-12-04 10:40:35 +0100494 rtcp::SenderReport* report = new rtcp::SenderReport();
495 report->From(ssrc_);
496 report->WithNtpSec(ctx.ntp_sec_);
497 report->WithNtpFrac(ctx.ntp_frac_);
498 report->WithRtpTimestamp(rtp_timestamp);
499 report->WithPacketCount(ctx.feedback_state_.packets_sent);
500 report->WithOctetCount(ctx.feedback_state_.media_bytes_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000501
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200502 for (auto it : report_blocks_)
Erik Språngf7c57762015-12-04 10:40:35 +0100503 report->WithReportBlock(it.second);
niklase@google.com470e71d2011-07-07 08:21:25 +0000504
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200505 report_blocks_.clear();
Erik Språngf7c57762015-12-04 10:40:35 +0100506
507 return rtc::scoped_ptr<rtcp::SenderReport>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000508}
509
Erik Språngf7c57762015-12-04 10:40:35 +0100510rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildSDES(
511 const RtcpContext& ctx) {
Erik Språng0ea42d32015-06-25 14:46:16 +0200512 size_t length_cname = cname_.length();
henrikg91d6ede2015-09-17 00:24:34 -0700513 RTC_CHECK_LT(length_cname, static_cast<size_t>(RTCP_CNAME_SIZE));
niklase@google.com470e71d2011-07-07 08:21:25 +0000514
Erik Språngf7c57762015-12-04 10:40:35 +0100515 rtcp::Sdes* sdes = new rtcp::Sdes();
516 sdes->WithCName(ssrc_, cname_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200517
518 for (const auto it : csrc_cnames_)
Erik Språngf7c57762015-12-04 10:40:35 +0100519 sdes->WithCName(it.first, it.second);
Erik Språng0ea42d32015-06-25 14:46:16 +0200520
Erik Språngf7c57762015-12-04 10:40:35 +0100521 return rtc::scoped_ptr<rtcp::Sdes>(sdes);
niklase@google.com470e71d2011-07-07 08:21:25 +0000522}
523
Erik Språngf7c57762015-12-04 10:40:35 +0100524rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildRR(const RtcpContext& ctx) {
525 rtcp::ReceiverReport* report = new rtcp::ReceiverReport();
526 report->From(ssrc_);
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200527 for (auto it : report_blocks_)
Erik Språngf7c57762015-12-04 10:40:35 +0100528 report->WithReportBlock(it.second);
Erik Språng61be2a42015-04-27 13:32:52 +0200529
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200530 report_blocks_.clear();
Erik Språngf7c57762015-12-04 10:40:35 +0100531 return rtc::scoped_ptr<rtcp::ReceiverReport>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000532}
533
Erik Språngf7c57762015-12-04 10:40:35 +0100534rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildPLI(const RtcpContext& ctx) {
535 rtcp::Pli* pli = new rtcp::Pli();
536 pli->From(ssrc_);
537 pli->To(remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200538
Erik Språng242e22b2015-05-11 10:17:43 +0200539 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
540 "RTCPSender::PLI");
541 ++packet_type_counter_.pli_packets;
542 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
543 ssrc_, packet_type_counter_.pli_packets);
544
Erik Språngf7c57762015-12-04 10:40:35 +0100545 return rtc::scoped_ptr<rtcp::Pli>(pli);
Erik Språng61be2a42015-04-27 13:32:52 +0200546}
547
Erik Språngf7c57762015-12-04 10:40:35 +0100548rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildFIR(const RtcpContext& ctx) {
549 if (!ctx.repeat_)
sprang62dae192015-08-05 02:35:35 -0700550 ++sequence_number_fir_; // Do not increase if repetition.
niklase@google.com470e71d2011-07-07 08:21:25 +0000551
Erik Språngf7c57762015-12-04 10:40:35 +0100552 rtcp::Fir* fir = new rtcp::Fir();
553 fir->From(ssrc_);
554 fir->To(remote_ssrc_);
555 fir->WithCommandSeqNum(sequence_number_fir_);
Erik Språng242e22b2015-05-11 10:17:43 +0200556
557 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
558 "RTCPSender::FIR");
559 ++packet_type_counter_.fir_packets;
560 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
561 ssrc_, packet_type_counter_.fir_packets);
562
Erik Språngf7c57762015-12-04 10:40:35 +0100563 return rtc::scoped_ptr<rtcp::Fir>(fir);
niklase@google.com470e71d2011-07-07 08:21:25 +0000564}
565
566/*
567 0 1 2 3
568 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
569 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
570 | First | Number | PictureID |
571 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
572*/
Erik Språngf7c57762015-12-04 10:40:35 +0100573rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildSLI(const RtcpContext& ctx) {
574 rtcp::Sli* sli = new rtcp::Sli();
575 sli->From(ssrc_);
576 sli->To(remote_ssrc_);
sprang0365a272015-08-11 01:02:37 -0700577 // Crop picture id to 6 least significant bits.
Erik Språngf7c57762015-12-04 10:40:35 +0100578 sli->WithPictureId(ctx.picture_id_ & 0x3F);
579 sli->WithFirstMb(0);
580 sli->WithNumberOfMb(0x1FFF); // 13 bits, only ones for now.
sprang0365a272015-08-11 01:02:37 -0700581
Erik Språngf7c57762015-12-04 10:40:35 +0100582 return rtc::scoped_ptr<rtcp::Sli>(sli);
niklase@google.com470e71d2011-07-07 08:21:25 +0000583}
584
585/*
586 0 1 2 3
587 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
588 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
589 | PB |0| Payload Type| Native RPSI bit string |
590 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
591 | defined per codec ... | Padding (0) |
592 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
593*/
594/*
595* Note: not generic made for VP8
596*/
Erik Språngf7c57762015-12-04 10:40:35 +0100597rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildRPSI(
598 const RtcpContext& ctx) {
599 if (ctx.feedback_state_.send_payload_type == 0xFF)
600 return nullptr;
Erik Språng242e22b2015-05-11 10:17:43 +0200601
Erik Språngf7c57762015-12-04 10:40:35 +0100602 rtcp::Rpsi* rpsi = new rtcp::Rpsi();
603 rpsi->From(ssrc_);
604 rpsi->To(remote_ssrc_);
605 rpsi->WithPayloadType(ctx.feedback_state_.send_payload_type);
606 rpsi->WithPictureId(ctx.picture_id_);
sprangcf7f54d2015-08-13 04:37:42 -0700607
Erik Språngf7c57762015-12-04 10:40:35 +0100608 return rtc::scoped_ptr<rtcp::Rpsi>(rpsi);
niklase@google.com470e71d2011-07-07 08:21:25 +0000609}
610
Erik Språngf7c57762015-12-04 10:40:35 +0100611rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildREMB(
612 const RtcpContext& ctx) {
613 rtcp::Remb* remb = new rtcp::Remb();
614 remb->From(ssrc_);
sprangdd4edc52015-08-21 04:21:51 -0700615 for (uint32_t ssrc : remb_ssrcs_)
Erik Språngf7c57762015-12-04 10:40:35 +0100616 remb->AppliesTo(ssrc);
617 remb->WithBitrateBps(remb_bitrate_);
Erik Språng61be2a42015-04-27 13:32:52 +0200618
Erik Språng242e22b2015-05-11 10:17:43 +0200619 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
620 "RTCPSender::REMB");
621
Erik Språngf7c57762015-12-04 10:40:35 +0100622 return rtc::scoped_ptr<rtcp::Remb>(remb);
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000623}
624
Erik Språng61be2a42015-04-27 13:32:52 +0200625void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
Erik Språng242e22b2015-05-11 10:17:43 +0200626 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
627 tmmbr_send_ = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000628}
629
Erik Språngf7c57762015-12-04 10:40:35 +0100630rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBR(
631 const RtcpContext& ctx) {
632 if (ctx.feedback_state_.module == nullptr)
633 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200634 // Before sending the TMMBR check the received TMMBN, only an owner is
635 // allowed to raise the bitrate:
636 // * If the sender is an owner of the TMMBN -> send TMMBR
637 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000638
Erik Språng61be2a42015-04-27 13:32:52 +0200639 // get current bounding set from RTCP receiver
640 bool tmmbrOwner = false;
641 // store in candidateSet, allocates one extra slot
Erik Språng242e22b2015-05-11 10:17:43 +0200642 TMMBRSet* candidateSet = tmmbr_help_.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000643
Erik Språng242e22b2015-05-11 10:17:43 +0200644 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
645 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
Erik Språng61be2a42015-04-27 13:32:52 +0200646 // since RTCPreceiver is not doing the reverse we should be fine
647 int32_t lengthOfBoundingSet =
Erik Språngf7c57762015-12-04 10:40:35 +0100648 ctx.feedback_state_.module->BoundingSet(tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +0000649
Erik Språng61be2a42015-04-27 13:32:52 +0200650 if (lengthOfBoundingSet > 0) {
651 for (int32_t i = 0; i < lengthOfBoundingSet; i++) {
Erik Språng242e22b2015-05-11 10:17:43 +0200652 if (candidateSet->Tmmbr(i) == tmmbr_send_ &&
653 candidateSet->PacketOH(i) == packet_oh_send_) {
Erik Språngf7c57762015-12-04 10:40:35 +0100654 // Do not send the same tuple.
655 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200656 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000657 }
Erik Språng61be2a42015-04-27 13:32:52 +0200658 if (!tmmbrOwner) {
659 // use received bounding set as candidate set
660 // add current tuple
Erik Språng242e22b2015-05-11 10:17:43 +0200661 candidateSet->SetEntry(lengthOfBoundingSet, tmmbr_send_, packet_oh_send_,
662 ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200663 int numCandidates = lengthOfBoundingSet + 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000664
Erik Språng61be2a42015-04-27 13:32:52 +0200665 // find bounding set
Erik Språngf7c57762015-12-04 10:40:35 +0100666 TMMBRSet* boundingSet = nullptr;
Erik Språng242e22b2015-05-11 10:17:43 +0200667 int numBoundingSet = tmmbr_help_.FindTMMBRBoundingSet(boundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200668 if (numBoundingSet > 0 || numBoundingSet <= numCandidates)
Erik Språng242e22b2015-05-11 10:17:43 +0200669 tmmbrOwner = tmmbr_help_.IsOwner(ssrc_, numBoundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200670 if (!tmmbrOwner) {
Erik Språngf7c57762015-12-04 10:40:35 +0100671 // Did not enter bounding set, no meaning to send this request.
672 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200673 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000674 }
Erik Språng61be2a42015-04-27 13:32:52 +0200675 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000676
Erik Språngf7c57762015-12-04 10:40:35 +0100677 if (!tmmbr_send_)
678 return nullptr;
sprang81a3e602015-08-21 05:30:11 -0700679
Erik Språngf7c57762015-12-04 10:40:35 +0100680 rtcp::Tmmbr* tmmbr = new rtcp::Tmmbr();
681 tmmbr->From(ssrc_);
682 tmmbr->To(remote_ssrc_);
683 tmmbr->WithBitrateKbps(tmmbr_send_);
684 tmmbr->WithOverhead(packet_oh_send_);
685
686 return rtc::scoped_ptr<rtcp::Tmmbr>(tmmbr);
Erik Språng61be2a42015-04-27 13:32:52 +0200687}
688
Erik Språngf7c57762015-12-04 10:40:35 +0100689rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBN(
690 const RtcpContext& ctx) {
Erik Språng242e22b2015-05-11 10:17:43 +0200691 TMMBRSet* boundingSet = tmmbr_help_.BoundingSetToSend();
Erik Språngf7c57762015-12-04 10:40:35 +0100692 if (boundingSet == nullptr)
693 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200694
Erik Språngf7c57762015-12-04 10:40:35 +0100695 rtcp::Tmmbn* tmmbn = new rtcp::Tmmbn();
696 tmmbn->From(ssrc_);
sprangd83df502015-08-27 01:05:08 -0700697 for (uint32_t i = 0; i < boundingSet->lengthOfSet(); i++) {
698 if (boundingSet->Tmmbr(i) > 0) {
Erik Språngf7c57762015-12-04 10:40:35 +0100699 tmmbn->WithTmmbr(boundingSet->Ssrc(i), boundingSet->Tmmbr(i),
700 boundingSet->PacketOH(i));
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000701 }
Erik Språng61be2a42015-04-27 13:32:52 +0200702 }
sprangd83df502015-08-27 01:05:08 -0700703
Erik Språngf7c57762015-12-04 10:40:35 +0100704 return rtc::scoped_ptr<rtcp::Tmmbn>(tmmbn);
niklase@google.com470e71d2011-07-07 08:21:25 +0000705}
706
Erik Språngf7c57762015-12-04 10:40:35 +0100707rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildAPP(const RtcpContext& ctx) {
708 rtcp::App* app = new rtcp::App();
709 app->From(ssrc_);
710 app->WithSubType(app_sub_type_);
711 app->WithName(app_name_);
712 app->WithData(app_data_.get(), app_length_);
Erik Språng521875a2015-09-01 10:11:16 +0200713
Erik Språngf7c57762015-12-04 10:40:35 +0100714 return rtc::scoped_ptr<rtcp::App>(app);
Erik Språng61be2a42015-04-27 13:32:52 +0200715}
716
Erik Språngf7c57762015-12-04 10:40:35 +0100717rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildNACK(
718 const RtcpContext& ctx) {
719 rtcp::Nack* nack = new rtcp::Nack();
720 nack->From(ssrc_);
721 nack->To(remote_ssrc_);
722 nack->WithList(ctx.nack_list_, ctx.nack_size_);
Erik Språng61be2a42015-04-27 13:32:52 +0200723
724 // Report stats.
725 NACKStringBuilder stringBuilder;
Erik Språngf7c57762015-12-04 10:40:35 +0100726 for (int idx = 0; idx < ctx.nack_size_; ++idx) {
727 stringBuilder.PushNACK(ctx.nack_list_[idx]);
728 nack_stats_.ReportRequest(ctx.nack_list_[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +0200729 }
Erik Språng61be2a42015-04-27 13:32:52 +0200730 packet_type_counter_.nack_requests = nack_stats_.requests();
731 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +0200732
733 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
734 "RTCPSender::NACK", "nacks",
735 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
736 ++packet_type_counter_.nack_packets;
737 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
738 ssrc_, packet_type_counter_.nack_packets);
739
Erik Språngf7c57762015-12-04 10:40:35 +0100740 return rtc::scoped_ptr<rtcp::Nack>(nack);
Erik Språng61be2a42015-04-27 13:32:52 +0200741}
742
Erik Språngf7c57762015-12-04 10:40:35 +0100743rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildBYE(const RtcpContext& ctx) {
744 rtcp::Bye* bye = new rtcp::Bye();
745 bye->From(ssrc_);
sprangd8ee4f92015-08-24 03:25:19 -0700746 for (uint32_t csrc : csrcs_)
Erik Språngf7c57762015-12-04 10:40:35 +0100747 bye->WithCsrc(csrc);
sprangd8ee4f92015-08-24 03:25:19 -0700748
Erik Språngf7c57762015-12-04 10:40:35 +0100749 return rtc::scoped_ptr<rtcp::Bye>(bye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000750}
751
Erik Språngf7c57762015-12-04 10:40:35 +0100752rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildReceiverReferenceTime(
753 const RtcpContext& ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200754 if (last_xr_rr_.size() >= RTCP_NUMBER_OF_SR)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000755 last_xr_rr_.erase(last_xr_rr_.begin());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000756 last_xr_rr_.insert(std::pair<uint32_t, int64_t>(
Erik Språngf7c57762015-12-04 10:40:35 +0100757 RTCPUtility::MidNtp(ctx.ntp_sec_, ctx.ntp_frac_),
758 Clock::NtpToMs(ctx.ntp_sec_, ctx.ntp_frac_)));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000759
Erik Språngf7c57762015-12-04 10:40:35 +0100760 rtcp::Xr* xr = new rtcp::Xr();
761 xr->From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000762
Erik Språngca28fdc2015-08-31 14:00:50 +0200763 rtcp::Rrtr rrtr;
Danil Chapovalovfc47ed62015-12-07 14:46:35 +0100764 rrtr.WithNtp(NtpTime(ctx.ntp_sec_, ctx.ntp_frac_));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000765
Erik Språngf7c57762015-12-04 10:40:35 +0100766 xr->WithRrtr(&rrtr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000767
Erik Språngca28fdc2015-08-31 14:00:50 +0200768 // TODO(sprang): Merge XR report sending to contain all of RRTR, DLRR, VOIP?
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000769
Erik Språngf7c57762015-12-04 10:40:35 +0100770 return rtc::scoped_ptr<rtcp::Xr>(xr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000771}
772
Erik Språngf7c57762015-12-04 10:40:35 +0100773rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildDlrr(
774 const RtcpContext& ctx) {
775 rtcp::Xr* xr = new rtcp::Xr();
776 xr->From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000777
Erik Språngca28fdc2015-08-31 14:00:50 +0200778 rtcp::Dlrr dlrr;
Erik Språngf7c57762015-12-04 10:40:35 +0100779 const RtcpReceiveTimeInfo& info = ctx.feedback_state_.last_xr_rr;
Erik Språngca28fdc2015-08-31 14:00:50 +0200780 dlrr.WithDlrrItem(info.sourceSSRC, info.lastRR, info.delaySinceLastRR);
781
Erik Språngf7c57762015-12-04 10:40:35 +0100782 xr->WithDlrr(&dlrr);
Erik Språngca28fdc2015-08-31 14:00:50 +0200783
Erik Språngf7c57762015-12-04 10:40:35 +0100784 return rtc::scoped_ptr<rtcp::Xr>(xr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000785}
786
Erik Språng242e22b2015-05-11 10:17:43 +0200787// TODO(sprang): Add a unit test for this, or remove if the code isn't used.
Erik Språngf7c57762015-12-04 10:40:35 +0100788rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildVoIPMetric(
789 const RtcpContext& context) {
790 rtcp::Xr* xr = new rtcp::Xr();
791 xr->From(ssrc_);
Erik Språngca28fdc2015-08-31 14:00:50 +0200792
793 rtcp::VoipMetric voip;
794 voip.To(remote_ssrc_);
795 voip.LossRate(xr_voip_metric_.lossRate);
796 voip.DiscardRate(xr_voip_metric_.discardRate);
797 voip.BurstDensity(xr_voip_metric_.burstDensity);
798 voip.GapDensity(xr_voip_metric_.gapDensity);
799 voip.BurstDuration(xr_voip_metric_.burstDuration);
800 voip.GapDuration(xr_voip_metric_.gapDuration);
801 voip.RoundTripDelay(xr_voip_metric_.roundTripDelay);
802 voip.EndSystemDelay(xr_voip_metric_.endSystemDelay);
803 voip.SignalLevel(xr_voip_metric_.signalLevel);
804 voip.NoiseLevel(xr_voip_metric_.noiseLevel);
805 voip.Rerl(xr_voip_metric_.RERL);
806 voip.Gmin(xr_voip_metric_.Gmin);
807 voip.Rfactor(xr_voip_metric_.Rfactor);
808 voip.ExtRfactor(xr_voip_metric_.extRfactor);
809 voip.MosLq(xr_voip_metric_.MOSLQ);
810 voip.MosCq(xr_voip_metric_.MOSCQ);
811 voip.RxConfig(xr_voip_metric_.RXconfig);
812 voip.JbNominal(xr_voip_metric_.JBnominal);
813 voip.JbMax(xr_voip_metric_.JBmax);
814 voip.JbAbsMax(xr_voip_metric_.JBabsMax);
815
Erik Språngf7c57762015-12-04 10:40:35 +0100816 xr->WithVoipMetric(&voip);
Erik Språngca28fdc2015-08-31 14:00:50 +0200817
Erik Språngf7c57762015-12-04 10:40:35 +0100818 return rtc::scoped_ptr<rtcp::Xr>(xr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000819}
820
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000821int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200822 RTCPPacketType packetType,
823 int32_t nack_size,
824 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000825 bool repeat,
826 uint64_t pictureID) {
Erik Språng242e22b2015-05-11 10:17:43 +0200827 return SendCompoundRTCP(
828 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
829 nack_size, nack_list, repeat, pictureID);
830}
831
832int32_t RTCPSender::SendCompoundRTCP(
833 const FeedbackState& feedback_state,
Erik Språngf7c57762015-12-04 10:40:35 +0100834 const std::set<RTCPPacketType>& packet_types,
Erik Språng242e22b2015-05-11 10:17:43 +0200835 int32_t nack_size,
836 const uint16_t* nack_list,
837 bool repeat,
838 uint64_t pictureID) {
Erik Språngf7c57762015-12-04 10:40:35 +0100839 PacketContainer container(transport_);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000840 {
Erik Språng242e22b2015-05-11 10:17:43 +0200841 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
pbosda903ea2015-10-02 02:36:56 -0700842 if (method_ == RtcpMode::kOff) {
Erik Språng61be2a42015-04-27 13:32:52 +0200843 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
844 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +0000845 }
Erik Språngf7c57762015-12-04 10:40:35 +0100846
847 // We need to send our NTP even if we haven't received any reports.
848 uint32_t ntp_sec;
849 uint32_t ntp_frac;
850 clock_->CurrentNtp(ntp_sec, ntp_frac);
851 RtcpContext context(feedback_state, nack_size, nack_list, repeat, pictureID,
852 ntp_sec, ntp_frac, &container);
853
854 PrepareReport(packet_types, feedback_state);
855
856 auto it = report_flags_.begin();
857 while (it != report_flags_.end()) {
858 auto builder_it = builders_.find(it->type);
859 RTC_DCHECK(builder_it != builders_.end());
860 if (it->is_volatile) {
861 report_flags_.erase(it++);
862 } else {
863 ++it;
864 }
865
866 BuilderFunc func = builder_it->second;
867 rtc::scoped_ptr<rtcp::RtcpPacket> packet = (this->*func)(context);
868 if (packet.get() == nullptr)
869 return -1;
870 container.Append(packet.release());
871 }
872
873 if (packet_type_counter_observer_ != nullptr) {
874 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
875 remote_ssrc_, packet_type_counter_);
876 }
877
878 RTC_DCHECK(AllVolatileFlagsConsumed());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000879 }
Erik Språng61be2a42015-04-27 13:32:52 +0200880
Erik Språngf7c57762015-12-04 10:40:35 +0100881 size_t bytes_sent = container.SendPackets();
882 return bytes_sent == 0 ? -1 : 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000883}
884
Erik Språngf7c57762015-12-04 10:40:35 +0100885void RTCPSender::PrepareReport(const std::set<RTCPPacketType>& packetTypes,
886 const FeedbackState& feedback_state) {
Erik Språng242e22b2015-05-11 10:17:43 +0200887 // Add all flags as volatile. Non volatile entries will not be overwritten
888 // and all new volatile flags added will be consumed by the end of this call.
889 SetFlags(packetTypes, true);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000890
Erik Språng61be2a42015-04-27 13:32:52 +0200891 if (packet_type_counter_.first_packet_time_ms == -1)
Erik Språng242e22b2015-05-11 10:17:43 +0200892 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språng61be2a42015-04-27 13:32:52 +0200893
Erik Språng242e22b2015-05-11 10:17:43 +0200894 bool generate_report;
895 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
896 // Report type already explicitly set, don't automatically populate.
897 generate_report = true;
henrikg91d6ede2015-09-17 00:24:34 -0700898 RTC_DCHECK(ConsumeFlag(kRtcpReport) == false);
Erik Språng242e22b2015-05-11 10:17:43 +0200899 } else {
900 generate_report =
pbosda903ea2015-10-02 02:36:56 -0700901 (ConsumeFlag(kRtcpReport) && method_ == RtcpMode::kReducedSize) ||
902 method_ == RtcpMode::kCompound;
Erik Språng242e22b2015-05-11 10:17:43 +0200903 if (generate_report)
904 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000905 }
906
Erik Språng0ea42d32015-06-25 14:46:16 +0200907 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
Erik Språng242e22b2015-05-11 10:17:43 +0200908 SetFlag(kRtcpSdes, true);
909
Erik Språng242e22b2015-05-11 10:17:43 +0200910 if (generate_report) {
911 if (!sending_ && xr_send_receiver_reference_time_enabled_)
912 SetFlag(kRtcpXrReceiverReferenceTime, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200913 if (feedback_state.has_last_xr_rr)
Erik Språng242e22b2015-05-11 10:17:43 +0200914 SetFlag(kRtcpXrDlrrReportBlock, true);
915
916 // generate next time to send an RTCP report
Erik Språng61be2a42015-04-27 13:32:52 +0200917 // seeded from RTP constructor
918 int32_t random = rand() % 1000;
919 int32_t timeToNext = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000920
Erik Språng242e22b2015-05-11 10:17:43 +0200921 if (audio_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200922 timeToNext = (RTCP_INTERVAL_AUDIO_MS / 2) +
923 (RTCP_INTERVAL_AUDIO_MS * random / 1000);
924 } else {
925 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
Erik Språng242e22b2015-05-11 10:17:43 +0200926 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200927 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
928 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
929 if (send_bitrate_kbit != 0)
930 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000931 }
Erik Språng61be2a42015-04-27 13:32:52 +0200932 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
933 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
934 timeToNext = (minIntervalMs / 2) + (minIntervalMs * random / 1000);
935 }
Erik Språng242e22b2015-05-11 10:17:43 +0200936 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000937
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000938 StatisticianMap statisticians =
939 receive_statistics_->GetActiveStatisticians();
940 if (!statisticians.empty()) {
Erik Språng61be2a42015-04-27 13:32:52 +0200941 for (auto it = statisticians.begin(); it != statisticians.end(); ++it) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000942 RTCPReportBlock report_block;
Erik Språngf7c57762015-12-04 10:40:35 +0100943 if (PrepareReportBlock(feedback_state, it->first, it->second,
944 &report_block)) {
danilchapdf948f02015-11-13 03:03:13 -0800945 // TODO(danilchap) AddReportBlock may fail (for 2 different reasons).
946 // Probably it shouldn't be ignored.
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200947 AddReportBlock(report_block);
Erik Språng61be2a42015-04-27 13:32:52 +0200948 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000949 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000950 }
951 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000952}
953
Erik Språngf7c57762015-12-04 10:40:35 +0100954bool RTCPSender::PrepareReportBlock(const FeedbackState& feedback_state,
955 uint32_t ssrc,
956 StreamStatistician* statistician,
957 RTCPReportBlock* report_block) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000958 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000959 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000960 if (!statistician->GetStatistics(&stats, true))
961 return false;
962 report_block->fractionLost = stats.fraction_lost;
963 report_block->cumulativeLost = stats.cumulative_lost;
danilchap162abd32015-12-10 02:39:40 -0800964 report_block->extendedHighSeqNum = stats.extended_max_sequence_number;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000965 report_block->jitter = stats.jitter;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200966 report_block->remoteSSRC = ssrc;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000967
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200968 // TODO(sprang): Do we really need separate time stamps for each report?
969 // Get our NTP as late as possible to avoid a race.
970 uint32_t ntp_secs;
971 uint32_t ntp_frac;
972 clock_->CurrentNtp(ntp_secs, ntp_frac);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000973
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200974 // Delay since last received report.
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000975 uint32_t delaySinceLastReceivedSR = 0;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000976 if ((feedback_state.last_rr_ntp_secs != 0) ||
977 (feedback_state.last_rr_ntp_frac != 0)) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200978 // Get the 16 lowest bits of seconds and the 16 highest bits of fractions.
979 uint32_t now = ntp_secs & 0x0000FFFF;
Erik Språng61be2a42015-04-27 13:32:52 +0200980 now <<= 16;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200981 now += (ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000982
Erik Språng61be2a42015-04-27 13:32:52 +0200983 uint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
984 receiveTime <<= 16;
985 receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000986
danilchap162abd32015-12-10 02:39:40 -0800987 delaySinceLastReceivedSR = now - receiveTime;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000988 }
989 report_block->delaySinceLastSR = delaySinceLastReceivedSR;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000990 report_block->lastSR = feedback_state.remote_sr;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000991 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000992}
993
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000994void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
995 assert(csrcs.size() <= kRtpCsrcSize);
Erik Språng242e22b2015-05-11 10:17:43 +0200996 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000997 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +0000998}
999
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001000int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
1001 uint32_t name,
1002 const uint8_t* data,
1003 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +02001004 if (length % 4 != 0) {
1005 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
1006 return -1;
1007 }
Erik Språng242e22b2015-05-11 10:17:43 +02001008 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +00001009
Erik Språng242e22b2015-05-11 10:17:43 +02001010 SetFlag(kRtcpApp, true);
1011 app_sub_type_ = subType;
1012 app_name_ = name;
1013 app_data_.reset(new uint8_t[length]);
1014 app_length_ = length;
1015 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +02001016 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001017}
1018
Erik Språng61be2a42015-04-27 13:32:52 +02001019int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
Erik Språng242e22b2015-05-11 10:17:43 +02001020 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1021 memcpy(&xr_voip_metric_, VoIPMetric, sizeof(RTCPVoIPMetric));
niklase@google.com470e71d2011-07-07 08:21:25 +00001022
Erik Språng242e22b2015-05-11 10:17:43 +02001023 SetFlag(kRtcpXrVoipMetric, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001024 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001025}
1026
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001027void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +02001028 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1029 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001030}
1031
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00001032bool RTCPSender::RtcpXrReceiverReferenceTime() const {
Erik Språng242e22b2015-05-11 10:17:43 +02001033 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1034 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00001035}
1036
niklase@google.com470e71d2011-07-07 08:21:25 +00001037// no callbacks allowed inside this function
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001038int32_t RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
1039 uint32_t maxBitrateKbit) {
Erik Språng242e22b2015-05-11 10:17:43 +02001040 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +00001041
Erik Språng242e22b2015-05-11 10:17:43 +02001042 if (0 == tmmbr_help_.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit)) {
1043 SetFlag(kRtcpTmmbn, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001044 return 0;
1045 }
1046 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001047}
Erik Språng61be2a42015-04-27 13:32:52 +02001048
Erik Språng242e22b2015-05-11 10:17:43 +02001049void RTCPSender::SetFlag(RTCPPacketType type, bool is_volatile) {
1050 report_flags_.insert(ReportFlag(type, is_volatile));
1051}
1052
1053void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
1054 bool is_volatile) {
1055 for (RTCPPacketType type : types)
1056 SetFlag(type, is_volatile);
1057}
1058
1059bool RTCPSender::IsFlagPresent(RTCPPacketType type) const {
1060 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
1061}
1062
1063bool RTCPSender::ConsumeFlag(RTCPPacketType type, bool forced) {
1064 auto it = report_flags_.find(ReportFlag(type, false));
1065 if (it == report_flags_.end())
1066 return false;
1067 if (it->is_volatile || forced)
1068 report_flags_.erase((it));
1069 return true;
1070}
1071
1072bool RTCPSender::AllVolatileFlagsConsumed() const {
1073 for (const ReportFlag& flag : report_flags_) {
1074 if (flag.is_volatile)
1075 return false;
1076 }
1077 return true;
1078}
1079
sprang233bd872015-09-08 13:25:16 -07001080bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
sprang233bd872015-09-08 13:25:16 -07001081 class Sender : public rtcp::RtcpPacket::PacketReadyCallback {
1082 public:
Peter Boströmac547a62015-09-17 23:03:57 +02001083 Sender(Transport* transport)
1084 : transport_(transport), send_failure_(false) {}
sprang233bd872015-09-08 13:25:16 -07001085
1086 void OnPacketReady(uint8_t* data, size_t length) override {
pbos2d566682015-09-28 09:59:31 -07001087 if (!transport_->SendRtcp(data, length))
sprang233bd872015-09-08 13:25:16 -07001088 send_failure_ = true;
1089 }
1090
1091 Transport* const transport_;
sprang233bd872015-09-08 13:25:16 -07001092 bool send_failure_;
sprang86fd9ed2015-09-29 04:45:43 -07001093 } sender(transport_);
sprang233bd872015-09-08 13:25:16 -07001094
1095 uint8_t buffer[IP_PACKET_SIZE];
1096 return packet.BuildExternalBuffer(buffer, IP_PACKET_SIZE, &sender) &&
1097 !sender.send_failure_;
1098}
1099
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001100} // namespace webrtc