blob: 03164f0a152f37d06c2976cb9e5b7182fdafab9e [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000011#include "webrtc/modules/rtp_rtcp/source/rtcp_sender.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000013#include <assert.h> // assert
stefan@webrtc.org9354cc92012-06-07 08:10:14 +000014#include <string.h> // memcpy
niklase@google.com470e71d2011-07-07 08:21:25 +000015
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000016#include <algorithm> // min
Erik Språng61be2a42015-04-27 13:32:52 +020017#include <limits> // max
danilchapb8b6fbb2015-12-10 05:05:27 -080018#include <utility>
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000019
Erik Språng61be2a42015-04-27 13:32:52 +020020#include "webrtc/base/checks.h"
Peter Boströmebc0b4e2015-10-28 16:39:33 +010021#include "webrtc/base/logging.h"
tommie4f96502015-10-20 23:00:48 -070022#include "webrtc/base/trace_event.h"
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000023#include "webrtc/common_types.h"
sprang@webrtc.org779c3d12015-03-17 16:42:49 +000024#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
danilchap0219c9b2015-11-18 05:56:53 -080025#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/app.h"
danilchap50c51362015-11-22 09:03:11 -080026#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/bye.h"
danilchap2f7dea12016-01-13 02:03:04 -080027#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/compound_packet.h"
danilchapa8890a52015-12-22 03:43:04 -080028#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/nack.h"
danilchapf8385ad2015-11-27 05:36:09 -080029#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/pli.h"
Danil Chapovalov97f7e132015-12-04 16:13:30 +010030#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
Danil Chapovalova5eba6c2016-01-15 12:40:15 +010031#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/remb.h"
danilchap92e677a2016-01-12 10:04:52 -080032#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sli.h"
danilchapef3d8052016-01-11 03:31:08 -080033#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbn.h"
danilchap7e8145f2016-01-11 11:49:19 -080034#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbr.h"
sprang233bd872015-09-08 13:25:16 -070035#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
tommie4f96502015-10-20 23:00:48 -070036#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010037#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000038
niklase@google.com470e71d2011-07-07 08:21:25 +000039namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000040
41using RTCPUtility::RTCPCnameInformation;
42
Erik Språng61be2a42015-04-27 13:32:52 +020043NACKStringBuilder::NACKStringBuilder()
danilchap162abd32015-12-10 02:39:40 -080044 : stream_(""), count_(0), prevNack_(0), consecutive_(false) {}
edjee@google.com79b02892013-04-04 19:43:34 +000045
pbos@webrtc.orgf3e4cee2013-07-31 15:17:19 +000046NACKStringBuilder::~NACKStringBuilder() {}
47
danilchap162abd32015-12-10 02:39:40 -080048void NACKStringBuilder::PushNACK(uint16_t nack) {
Erik Språng242e22b2015-05-11 10:17:43 +020049 if (count_ == 0) {
50 stream_ << nack;
51 } else if (nack == prevNack_ + 1) {
52 consecutive_ = true;
Erik Språng61be2a42015-04-27 13:32:52 +020053 } else {
Erik Språng242e22b2015-05-11 10:17:43 +020054 if (consecutive_) {
55 stream_ << "-" << prevNack_;
56 consecutive_ = false;
edjee@google.com79b02892013-04-04 19:43:34 +000057 }
Erik Språng242e22b2015-05-11 10:17:43 +020058 stream_ << "," << nack;
Erik Språng61be2a42015-04-27 13:32:52 +020059 }
Erik Språng242e22b2015-05-11 10:17:43 +020060 count_++;
61 prevNack_ = nack;
edjee@google.com79b02892013-04-04 19:43:34 +000062}
63
Erik Språng61be2a42015-04-27 13:32:52 +020064std::string NACKStringBuilder::GetResult() {
Erik Språng242e22b2015-05-11 10:17:43 +020065 if (consecutive_) {
66 stream_ << "-" << prevNack_;
67 consecutive_ = false;
Erik Språng61be2a42015-04-27 13:32:52 +020068 }
Erik Språng242e22b2015-05-11 10:17:43 +020069 return stream_.str();
edjee@google.com79b02892013-04-04 19:43:34 +000070}
71
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000072RTCPSender::FeedbackState::FeedbackState()
73 : send_payload_type(0),
74 frequency_hz(0),
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +000075 packets_sent(0),
76 media_bytes_sent(0),
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000077 send_bitrate(0),
78 last_rr_ntp_secs(0),
79 last_rr_ntp_frac(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000080 remote_sr(0),
Erik Språng61be2a42015-04-27 13:32:52 +020081 has_last_xr_rr(false),
danilchap162abd32015-12-10 02:39:40 -080082 module(nullptr) {}
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000083
danilchap2f7dea12016-01-13 02:03:04 -080084class PacketContainer : public rtcp::CompoundPacket,
Erik Språngf7c57762015-12-04 10:40:35 +010085 public rtcp::RtcpPacket::PacketReadyCallback {
86 public:
87 explicit PacketContainer(Transport* transport)
88 : transport_(transport), bytes_sent_(0) {}
89 virtual ~PacketContainer() {
90 for (RtcpPacket* packet : appended_packets_)
91 delete packet;
92 }
93
94 void OnPacketReady(uint8_t* data, size_t length) override {
95 if (transport_->SendRtcp(data, length))
96 bytes_sent_ += length;
97 }
98
99 size_t SendPackets() {
danilchap2f7dea12016-01-13 02:03:04 -0800100 rtcp::CompoundPacket::Build(this);
Erik Språngf7c57762015-12-04 10:40:35 +0100101 return bytes_sent_;
102 }
103
104 private:
105 Transport* transport_;
106 size_t bytes_sent_;
107};
108
109class RTCPSender::RtcpContext {
110 public:
Erik Språng242e22b2015-05-11 10:17:43 +0200111 RtcpContext(const FeedbackState& feedback_state,
112 int32_t nack_size,
113 const uint16_t* nack_list,
114 bool repeat,
115 uint64_t picture_id,
Erik Språngf7c57762015-12-04 10:40:35 +0100116 uint32_t ntp_sec,
117 uint32_t ntp_frac,
118 PacketContainer* container)
119 : feedback_state_(feedback_state),
120 nack_size_(nack_size),
121 nack_list_(nack_list),
122 repeat_(repeat),
123 picture_id_(picture_id),
124 ntp_sec_(ntp_sec),
125 ntp_frac_(ntp_frac),
126 container_(container) {}
Erik Språng242e22b2015-05-11 10:17:43 +0200127
Erik Språngf7c57762015-12-04 10:40:35 +0100128 virtual ~RtcpContext() {}
Erik Språng242e22b2015-05-11 10:17:43 +0200129
Erik Språngf7c57762015-12-04 10:40:35 +0100130 const FeedbackState& feedback_state_;
131 const int32_t nack_size_;
132 const uint16_t* nack_list_;
133 const bool repeat_;
134 const uint64_t picture_id_;
135 const uint32_t ntp_sec_;
136 const uint32_t ntp_frac_;
Erik Språng242e22b2015-05-11 10:17:43 +0200137
Erik Språngf7c57762015-12-04 10:40:35 +0100138 PacketContainer* const container_;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200139};
140
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000141RTCPSender::RTCPSender(
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000142 bool audio,
143 Clock* clock,
144 ReceiveStatistics* receive_statistics,
sprang86fd9ed2015-09-29 04:45:43 -0700145 RtcpPacketTypeCounterObserver* packet_type_counter_observer,
146 Transport* outgoing_transport)
Peter Boströmac547a62015-09-17 23:03:57 +0200147 : audio_(audio),
Erik Språng242e22b2015-05-11 10:17:43 +0200148 clock_(clock),
danilchap47a740b2015-12-15 00:30:07 -0800149 random_(clock_->TimeInMicroseconds()),
pbosda903ea2015-10-02 02:36:56 -0700150 method_(RtcpMode::kOff),
sprang86fd9ed2015-09-29 04:45:43 -0700151 transport_(outgoing_transport),
niklase@google.com470e71d2011-07-07 08:21:25 +0000152
Erik Språng242e22b2015-05-11 10:17:43 +0200153 critical_section_rtcp_sender_(
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000154 CriticalSectionWrapper::CreateCriticalSection()),
Erik Språng242e22b2015-05-11 10:17:43 +0200155 using_nack_(false),
156 sending_(false),
157 remb_enabled_(false),
Erik Språng242e22b2015-05-11 10:17:43 +0200158 next_time_to_send_rtcp_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000159 start_timestamp_(0),
160 last_rtp_timestamp_(0),
161 last_frame_capture_time_ms_(-1),
Erik Språng242e22b2015-05-11 10:17:43 +0200162 ssrc_(0),
163 remote_ssrc_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000164 receive_statistics_(receive_statistics),
niklase@google.com470e71d2011-07-07 08:21:25 +0000165
Erik Språng242e22b2015-05-11 10:17:43 +0200166 sequence_number_fir_(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000167
Erik Språng242e22b2015-05-11 10:17:43 +0200168 remb_bitrate_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000169
Erik Språng242e22b2015-05-11 10:17:43 +0200170 tmmbr_help_(),
171 tmmbr_send_(0),
172 packet_oh_send_(0),
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000173
Erik Språng242e22b2015-05-11 10:17:43 +0200174 app_sub_type_(0),
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200175 app_name_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200176 app_data_(nullptr),
177 app_length_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000178
Erik Språng242e22b2015-05-11 10:17:43 +0200179 xr_send_receiver_reference_time_enabled_(false),
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000180 packet_type_counter_observer_(packet_type_counter_observer) {
Erik Språng242e22b2015-05-11 10:17:43 +0200181 memset(last_send_report_, 0, sizeof(last_send_report_));
182 memset(last_rtcp_time_, 0, sizeof(last_rtcp_time_));
sprang86fd9ed2015-09-29 04:45:43 -0700183 RTC_DCHECK(transport_ != nullptr);
Erik Språng242e22b2015-05-11 10:17:43 +0200184
185 builders_[kRtcpSr] = &RTCPSender::BuildSR;
186 builders_[kRtcpRr] = &RTCPSender::BuildRR;
Erik Språng0ea42d32015-06-25 14:46:16 +0200187 builders_[kRtcpSdes] = &RTCPSender::BuildSDES;
Erik Språng242e22b2015-05-11 10:17:43 +0200188 builders_[kRtcpPli] = &RTCPSender::BuildPLI;
189 builders_[kRtcpFir] = &RTCPSender::BuildFIR;
190 builders_[kRtcpSli] = &RTCPSender::BuildSLI;
191 builders_[kRtcpRpsi] = &RTCPSender::BuildRPSI;
192 builders_[kRtcpRemb] = &RTCPSender::BuildREMB;
193 builders_[kRtcpBye] = &RTCPSender::BuildBYE;
194 builders_[kRtcpApp] = &RTCPSender::BuildAPP;
195 builders_[kRtcpTmmbr] = &RTCPSender::BuildTMMBR;
196 builders_[kRtcpTmmbn] = &RTCPSender::BuildTMMBN;
197 builders_[kRtcpNack] = &RTCPSender::BuildNACK;
198 builders_[kRtcpXrVoipMetric] = &RTCPSender::BuildVoIPMetric;
199 builders_[kRtcpXrReceiverReferenceTime] =
200 &RTCPSender::BuildReceiverReferenceTime;
201 builders_[kRtcpXrDlrrReportBlock] = &RTCPSender::BuildDlrr;
niklase@google.com470e71d2011-07-07 08:21:25 +0000202}
203
danilchap162abd32015-12-10 02:39:40 -0800204RTCPSender::~RTCPSender() {}
niklase@google.com470e71d2011-07-07 08:21:25 +0000205
pbosda903ea2015-10-02 02:36:56 -0700206RtcpMode RTCPSender::Status() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200207 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
208 return method_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000209}
210
pbosda903ea2015-10-02 02:36:56 -0700211void RTCPSender::SetRTCPStatus(RtcpMode method) {
Erik Språng242e22b2015-05-11 10:17:43 +0200212 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
213 method_ = method;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000214
pbosda903ea2015-10-02 02:36:56 -0700215 if (method == RtcpMode::kOff)
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000216 return;
Erik Språng242e22b2015-05-11 10:17:43 +0200217 next_time_to_send_rtcp_ =
218 clock_->TimeInMilliseconds() +
219 (audio_ ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000220}
221
Erik Språng61be2a42015-04-27 13:32:52 +0200222bool RTCPSender::Sending() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200223 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
224 return sending_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000225}
226
Erik Språng61be2a42015-04-27 13:32:52 +0200227int32_t RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
228 bool sending) {
229 bool sendRTCPBye = false;
230 {
Erik Språng242e22b2015-05-11 10:17:43 +0200231 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000232
pbosda903ea2015-10-02 02:36:56 -0700233 if (method_ != RtcpMode::kOff) {
Erik Språng242e22b2015-05-11 10:17:43 +0200234 if (sending == false && sending_ == true) {
Erik Språng61be2a42015-04-27 13:32:52 +0200235 // Trigger RTCP bye
236 sendRTCPBye = true;
237 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000238 }
Erik Språng242e22b2015-05-11 10:17:43 +0200239 sending_ = sending;
Erik Språng61be2a42015-04-27 13:32:52 +0200240 }
241 if (sendRTCPBye)
242 return SendRTCP(feedback_state, kRtcpBye);
243 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000244}
245
Erik Språng61be2a42015-04-27 13:32:52 +0200246bool RTCPSender::REMB() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200247 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
248 return remb_enabled_;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000249}
250
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000251void RTCPSender::SetREMBStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200252 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
253 remb_enabled_ = enable;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000254}
255
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000256void RTCPSender::SetREMBData(uint32_t bitrate,
257 const std::vector<uint32_t>& ssrcs) {
Erik Språng242e22b2015-05-11 10:17:43 +0200258 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
259 remb_bitrate_ = bitrate;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000260 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000261
Erik Språng242e22b2015-05-11 10:17:43 +0200262 if (remb_enabled_)
263 SetFlag(kRtcpRemb, false);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000264 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
265 // throttled by the caller.
Erik Språng242e22b2015-05-11 10:17:43 +0200266 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000267}
268
Erik Språng61be2a42015-04-27 13:32:52 +0200269bool RTCPSender::TMMBR() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200270 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
271 return IsFlagPresent(RTCPPacketType::kRtcpTmmbr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000272}
273
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000274void RTCPSender::SetTMMBRStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200275 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
276 if (enable) {
277 SetFlag(RTCPPacketType::kRtcpTmmbr, false);
278 } else {
279 ConsumeFlag(RTCPPacketType::kRtcpTmmbr, true);
280 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000281}
282
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000283void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
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 start_timestamp_ = start_timestamp;
286}
287
288void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
289 int64_t capture_time_ms) {
Erik Språng242e22b2015-05-11 10:17:43 +0200290 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000291 last_rtp_timestamp_ = rtp_timestamp;
292 if (capture_time_ms < 0) {
293 // We don't currently get a capture time from VoiceEngine.
Erik Språng242e22b2015-05-11 10:17:43 +0200294 last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000295 } else {
296 last_frame_capture_time_ms_ = capture_time_ms;
297 }
298}
299
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000300void RTCPSender::SetSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200301 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000302
Erik Språng242e22b2015-05-11 10:17:43 +0200303 if (ssrc_ != 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200304 // not first SetSSRC, probably due to a collision
305 // schedule a new RTCP report
306 // make sure that we send a RTP packet
Erik Språng242e22b2015-05-11 10:17:43 +0200307 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
Erik Språng61be2a42015-04-27 13:32:52 +0200308 }
Erik Språng242e22b2015-05-11 10:17:43 +0200309 ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000310}
311
Erik Språng61be2a42015-04-27 13:32:52 +0200312void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200313 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
314 remote_ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000315}
316
Peter Boström9ba52f82015-06-01 14:12:28 +0200317int32_t RTCPSender::SetCNAME(const char* c_name) {
318 if (!c_name)
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000319 return -1;
320
henrikg91d6ede2015-09-17 00:24:34 -0700321 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
Erik Språng242e22b2015-05-11 10:17:43 +0200322 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200323 cname_ = c_name;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000324 return 0;
325}
326
Erik Språng0ea42d32015-06-25 14:46:16 +0200327int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC, const char* c_name) {
328 assert(c_name);
henrikg91d6ede2015-09-17 00:24:34 -0700329 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
Erik Språng242e22b2015-05-11 10:17:43 +0200330 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200331 if (csrc_cnames_.size() >= kRtpCsrcSize)
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000332 return -1;
Erik Språng0ea42d32015-06-25 14:46:16 +0200333
334 csrc_cnames_[SSRC] = c_name;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000335 return 0;
336}
337
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000338int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
Erik Språng242e22b2015-05-11 10:17:43 +0200339 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200340 auto it = csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000341
Erik Språng242e22b2015-05-11 10:17:43 +0200342 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000343 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200344
Erik Språng242e22b2015-05-11 10:17:43 +0200345 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000346 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000347}
348
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000349bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
danilchap162abd32015-12-10 02:39:40 -0800350 /*
351 For audio we use a fix 5 sec interval
niklase@google.com470e71d2011-07-07 08:21:25 +0000352
danilchap162abd32015-12-10 02:39:40 -0800353 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
354 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
355 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000356
357
danilchap162abd32015-12-10 02:39:40 -0800358 From RFC 3550
niklase@google.com470e71d2011-07-07 08:21:25 +0000359
danilchap162abd32015-12-10 02:39:40 -0800360 MAX RTCP BW is 5% if the session BW
361 A send report is approximately 65 bytes inc CNAME
362 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000363
danilchap162abd32015-12-10 02:39:40 -0800364 The RECOMMENDED value for the reduced minimum in seconds is 360
365 divided by the session bandwidth in kilobits/second. This minimum
366 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
niklase@google.com470e71d2011-07-07 08:21:25 +0000367
danilchap162abd32015-12-10 02:39:40 -0800368 If the participant has not yet sent an RTCP packet (the variable
369 initial is true), the constant Tmin is set to 2.5 seconds, else it
370 is set to 5 seconds.
niklase@google.com470e71d2011-07-07 08:21:25 +0000371
danilchap162abd32015-12-10 02:39:40 -0800372 The interval between RTCP packets is varied randomly over the
373 range [0.5,1.5] times the calculated interval to avoid unintended
374 synchronization of all participants
niklase@google.com470e71d2011-07-07 08:21:25 +0000375
danilchap162abd32015-12-10 02:39:40 -0800376 if we send
377 If the participant is a sender (we_sent true), the constant C is
378 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
379 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
380 number of senders.
niklase@google.com470e71d2011-07-07 08:21:25 +0000381
danilchap162abd32015-12-10 02:39:40 -0800382 if we receive only
383 If we_sent is not true, the constant C is set
384 to the average RTCP packet size divided by 75% of the RTCP
385 bandwidth. The constant n is set to the number of receivers
386 (members - senders). If the number of senders is greater than
387 25%, senders and receivers are treated together.
niklase@google.com470e71d2011-07-07 08:21:25 +0000388
danilchap162abd32015-12-10 02:39:40 -0800389 reconsideration NOT required for peer-to-peer
390 "timer reconsideration" is
391 employed. This algorithm implements a simple back-off mechanism
392 which causes users to hold back RTCP packet transmission if the
393 group sizes are increasing.
niklase@google.com470e71d2011-07-07 08:21:25 +0000394
danilchap162abd32015-12-10 02:39:40 -0800395 n = number of members
396 C = avg_size/(rtcpBW/4)
niklase@google.com470e71d2011-07-07 08:21:25 +0000397
danilchap162abd32015-12-10 02:39:40 -0800398 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
niklase@google.com470e71d2011-07-07 08:21:25 +0000399
danilchap162abd32015-12-10 02:39:40 -0800400 4. The calculated interval T is set to a number uniformly distributed
401 between 0.5 and 1.5 times the deterministic calculated interval.
niklase@google.com470e71d2011-07-07 08:21:25 +0000402
danilchap162abd32015-12-10 02:39:40 -0800403 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
404 for the fact that the timer reconsideration algorithm converges to
405 a value of the RTCP bandwidth below the intended average
406 */
niklase@google.com470e71d2011-07-07 08:21:25 +0000407
Erik Språng242e22b2015-05-11 10:17:43 +0200408 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000409
Erik Språng242e22b2015-05-11 10:17:43 +0200410 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
xians@webrtc.org8738d272011-11-25 13:43:53 +0000411
pbosda903ea2015-10-02 02:36:56 -0700412 if (method_ == RtcpMode::kOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000413 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000414
Erik Språng242e22b2015-05-11 10:17:43 +0200415 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200416 // for video key-frames we want to send the RTCP before the large key-frame
417 // if we have a 100 ms margin
418 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
419 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000420
Erik Språng242e22b2015-05-11 10:17:43 +0200421 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200422 return true;
423 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200424 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200425 // wrap
426 return true;
427 }
428 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000429}
430
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000431int64_t RTCPSender::SendTimeOfSendReport(uint32_t sendReport) {
Erik Språng242e22b2015-05-11 10:17:43 +0200432 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000433
Erik Språng61be2a42015-04-27 13:32:52 +0200434 // This is only saved when we are the sender
Erik Språng242e22b2015-05-11 10:17:43 +0200435 if ((last_send_report_[0] == 0) || (sendReport == 0)) {
Erik Språng61be2a42015-04-27 13:32:52 +0200436 return 0; // will be ignored
437 } else {
438 for (int i = 0; i < RTCP_NUMBER_OF_SR; ++i) {
Erik Språng242e22b2015-05-11 10:17:43 +0200439 if (last_send_report_[i] == sendReport)
440 return last_rtcp_time_[i];
niklase@google.com470e71d2011-07-07 08:21:25 +0000441 }
Erik Språng61be2a42015-04-27 13:32:52 +0200442 }
443 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000444}
445
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000446bool RTCPSender::SendTimeOfXrRrReport(uint32_t mid_ntp,
447 int64_t* time_ms) const {
Erik Språng242e22b2015-05-11 10:17:43 +0200448 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000449
450 if (last_xr_rr_.empty()) {
451 return false;
452 }
453 std::map<uint32_t, int64_t>::const_iterator it = last_xr_rr_.find(mid_ntp);
454 if (it == last_xr_rr_.end()) {
455 return false;
456 }
457 *time_ms = it->second;
458 return true;
459}
460
Erik Språngf7c57762015-12-04 10:40:35 +0100461rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildSR(const RtcpContext& ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200462 for (int i = (RTCP_NUMBER_OF_SR - 2); i >= 0; i--) {
463 // shift old
Erik Språng242e22b2015-05-11 10:17:43 +0200464 last_send_report_[i + 1] = last_send_report_[i];
465 last_rtcp_time_[i + 1] = last_rtcp_time_[i];
Erik Språng61be2a42015-04-27 13:32:52 +0200466 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000467
Erik Språngf7c57762015-12-04 10:40:35 +0100468 last_rtcp_time_[0] = Clock::NtpToMs(ctx.ntp_sec_, ctx.ntp_frac_);
469 last_send_report_[0] = (ctx.ntp_sec_ << 16) + (ctx.ntp_frac_ >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000470
Erik Språng61be2a42015-04-27 13:32:52 +0200471 // The timestamp of this RTCP packet should be estimated as the timestamp of
472 // the frame being captured at this moment. We are calculating that
473 // timestamp as the last frame's timestamp + the time since the last frame
474 // was captured.
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200475 uint32_t rtp_timestamp =
476 start_timestamp_ + last_rtp_timestamp_ +
477 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) *
Erik Språngf7c57762015-12-04 10:40:35 +0100478 (ctx.feedback_state_.frequency_hz / 1000);
niklase@google.com470e71d2011-07-07 08:21:25 +0000479
Erik Språngf7c57762015-12-04 10:40:35 +0100480 rtcp::SenderReport* report = new rtcp::SenderReport();
481 report->From(ssrc_);
482 report->WithNtpSec(ctx.ntp_sec_);
483 report->WithNtpFrac(ctx.ntp_frac_);
484 report->WithRtpTimestamp(rtp_timestamp);
485 report->WithPacketCount(ctx.feedback_state_.packets_sent);
486 report->WithOctetCount(ctx.feedback_state_.media_bytes_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000487
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200488 for (auto it : report_blocks_)
Erik Språngf7c57762015-12-04 10:40:35 +0100489 report->WithReportBlock(it.second);
niklase@google.com470e71d2011-07-07 08:21:25 +0000490
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200491 report_blocks_.clear();
Erik Språngf7c57762015-12-04 10:40:35 +0100492
493 return rtc::scoped_ptr<rtcp::SenderReport>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000494}
495
Erik Språngf7c57762015-12-04 10:40:35 +0100496rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildSDES(
497 const RtcpContext& ctx) {
Erik Språng0ea42d32015-06-25 14:46:16 +0200498 size_t length_cname = cname_.length();
henrikg91d6ede2015-09-17 00:24:34 -0700499 RTC_CHECK_LT(length_cname, static_cast<size_t>(RTCP_CNAME_SIZE));
niklase@google.com470e71d2011-07-07 08:21:25 +0000500
Erik Språngf7c57762015-12-04 10:40:35 +0100501 rtcp::Sdes* sdes = new rtcp::Sdes();
502 sdes->WithCName(ssrc_, cname_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200503
504 for (const auto it : csrc_cnames_)
Erik Språngf7c57762015-12-04 10:40:35 +0100505 sdes->WithCName(it.first, it.second);
Erik Språng0ea42d32015-06-25 14:46:16 +0200506
Erik Språngf7c57762015-12-04 10:40:35 +0100507 return rtc::scoped_ptr<rtcp::Sdes>(sdes);
niklase@google.com470e71d2011-07-07 08:21:25 +0000508}
509
Erik Språngf7c57762015-12-04 10:40:35 +0100510rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildRR(const RtcpContext& ctx) {
511 rtcp::ReceiverReport* report = new rtcp::ReceiverReport();
512 report->From(ssrc_);
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200513 for (auto it : report_blocks_)
Erik Språngf7c57762015-12-04 10:40:35 +0100514 report->WithReportBlock(it.second);
Erik Språng61be2a42015-04-27 13:32:52 +0200515
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200516 report_blocks_.clear();
Erik Språngf7c57762015-12-04 10:40:35 +0100517 return rtc::scoped_ptr<rtcp::ReceiverReport>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000518}
519
Erik Språngf7c57762015-12-04 10:40:35 +0100520rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildPLI(const RtcpContext& ctx) {
521 rtcp::Pli* pli = new rtcp::Pli();
522 pli->From(ssrc_);
523 pli->To(remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200524
Erik Språng242e22b2015-05-11 10:17:43 +0200525 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
526 "RTCPSender::PLI");
527 ++packet_type_counter_.pli_packets;
528 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
529 ssrc_, packet_type_counter_.pli_packets);
530
Erik Språngf7c57762015-12-04 10:40:35 +0100531 return rtc::scoped_ptr<rtcp::Pli>(pli);
Erik Språng61be2a42015-04-27 13:32:52 +0200532}
533
Erik Språngf7c57762015-12-04 10:40:35 +0100534rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildFIR(const RtcpContext& ctx) {
535 if (!ctx.repeat_)
sprang62dae192015-08-05 02:35:35 -0700536 ++sequence_number_fir_; // Do not increase if repetition.
niklase@google.com470e71d2011-07-07 08:21:25 +0000537
Erik Språngf7c57762015-12-04 10:40:35 +0100538 rtcp::Fir* fir = new rtcp::Fir();
539 fir->From(ssrc_);
540 fir->To(remote_ssrc_);
541 fir->WithCommandSeqNum(sequence_number_fir_);
Erik Språng242e22b2015-05-11 10:17:43 +0200542
543 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
544 "RTCPSender::FIR");
545 ++packet_type_counter_.fir_packets;
546 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
547 ssrc_, packet_type_counter_.fir_packets);
548
Erik Språngf7c57762015-12-04 10:40:35 +0100549 return rtc::scoped_ptr<rtcp::Fir>(fir);
niklase@google.com470e71d2011-07-07 08:21:25 +0000550}
551
552/*
553 0 1 2 3
554 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
555 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
556 | First | Number | PictureID |
557 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
558*/
Erik Språngf7c57762015-12-04 10:40:35 +0100559rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildSLI(const RtcpContext& ctx) {
560 rtcp::Sli* sli = new rtcp::Sli();
561 sli->From(ssrc_);
562 sli->To(remote_ssrc_);
sprang0365a272015-08-11 01:02:37 -0700563 // Crop picture id to 6 least significant bits.
Erik Språngf7c57762015-12-04 10:40:35 +0100564 sli->WithPictureId(ctx.picture_id_ & 0x3F);
sprang0365a272015-08-11 01:02:37 -0700565
Erik Språngf7c57762015-12-04 10:40:35 +0100566 return rtc::scoped_ptr<rtcp::Sli>(sli);
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 | PB |0| Payload Type| Native RPSI bit string |
574 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
575 | defined per codec ... | Padding (0) |
576 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
577*/
578/*
579* Note: not generic made for VP8
580*/
Erik Språngf7c57762015-12-04 10:40:35 +0100581rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildRPSI(
582 const RtcpContext& ctx) {
583 if (ctx.feedback_state_.send_payload_type == 0xFF)
584 return nullptr;
Erik Språng242e22b2015-05-11 10:17:43 +0200585
Erik Språngf7c57762015-12-04 10:40:35 +0100586 rtcp::Rpsi* rpsi = new rtcp::Rpsi();
587 rpsi->From(ssrc_);
588 rpsi->To(remote_ssrc_);
589 rpsi->WithPayloadType(ctx.feedback_state_.send_payload_type);
590 rpsi->WithPictureId(ctx.picture_id_);
sprangcf7f54d2015-08-13 04:37:42 -0700591
Erik Språngf7c57762015-12-04 10:40:35 +0100592 return rtc::scoped_ptr<rtcp::Rpsi>(rpsi);
niklase@google.com470e71d2011-07-07 08:21:25 +0000593}
594
Erik Språngf7c57762015-12-04 10:40:35 +0100595rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildREMB(
596 const RtcpContext& ctx) {
597 rtcp::Remb* remb = new rtcp::Remb();
598 remb->From(ssrc_);
sprangdd4edc52015-08-21 04:21:51 -0700599 for (uint32_t ssrc : remb_ssrcs_)
Erik Språngf7c57762015-12-04 10:40:35 +0100600 remb->AppliesTo(ssrc);
601 remb->WithBitrateBps(remb_bitrate_);
Erik Språng61be2a42015-04-27 13:32:52 +0200602
Erik Språng242e22b2015-05-11 10:17:43 +0200603 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
604 "RTCPSender::REMB");
605
Erik Språngf7c57762015-12-04 10:40:35 +0100606 return rtc::scoped_ptr<rtcp::Remb>(remb);
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000607}
608
Erik Språng61be2a42015-04-27 13:32:52 +0200609void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
Erik Språng242e22b2015-05-11 10:17:43 +0200610 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
611 tmmbr_send_ = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000612}
613
Erik Språngf7c57762015-12-04 10:40:35 +0100614rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBR(
615 const RtcpContext& ctx) {
616 if (ctx.feedback_state_.module == nullptr)
617 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200618 // Before sending the TMMBR check the received TMMBN, only an owner is
619 // allowed to raise the bitrate:
620 // * If the sender is an owner of the TMMBN -> send TMMBR
621 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000622
Erik Språng61be2a42015-04-27 13:32:52 +0200623 // get current bounding set from RTCP receiver
624 bool tmmbrOwner = false;
625 // store in candidateSet, allocates one extra slot
Erik Språng242e22b2015-05-11 10:17:43 +0200626 TMMBRSet* candidateSet = tmmbr_help_.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000627
Erik Språng242e22b2015-05-11 10:17:43 +0200628 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
629 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
Erik Språng61be2a42015-04-27 13:32:52 +0200630 // since RTCPreceiver is not doing the reverse we should be fine
631 int32_t lengthOfBoundingSet =
danilchap6db6cdc2015-12-15 02:54:47 -0800632 ctx.feedback_state_.module->BoundingSet(&tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +0000633
Erik Språng61be2a42015-04-27 13:32:52 +0200634 if (lengthOfBoundingSet > 0) {
635 for (int32_t i = 0; i < lengthOfBoundingSet; i++) {
Erik Språng242e22b2015-05-11 10:17:43 +0200636 if (candidateSet->Tmmbr(i) == tmmbr_send_ &&
637 candidateSet->PacketOH(i) == packet_oh_send_) {
Erik Språngf7c57762015-12-04 10:40:35 +0100638 // Do not send the same tuple.
639 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200640 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000641 }
Erik Språng61be2a42015-04-27 13:32:52 +0200642 if (!tmmbrOwner) {
643 // use received bounding set as candidate set
644 // add current tuple
Erik Språng242e22b2015-05-11 10:17:43 +0200645 candidateSet->SetEntry(lengthOfBoundingSet, tmmbr_send_, packet_oh_send_,
646 ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200647 int numCandidates = lengthOfBoundingSet + 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000648
Erik Språng61be2a42015-04-27 13:32:52 +0200649 // find bounding set
Erik Språngf7c57762015-12-04 10:40:35 +0100650 TMMBRSet* boundingSet = nullptr;
Erik Språng242e22b2015-05-11 10:17:43 +0200651 int numBoundingSet = tmmbr_help_.FindTMMBRBoundingSet(boundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200652 if (numBoundingSet > 0 || numBoundingSet <= numCandidates)
Erik Språng242e22b2015-05-11 10:17:43 +0200653 tmmbrOwner = tmmbr_help_.IsOwner(ssrc_, numBoundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200654 if (!tmmbrOwner) {
Erik Språngf7c57762015-12-04 10:40:35 +0100655 // Did not enter bounding set, no meaning to send this request.
656 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200657 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000658 }
Erik Språng61be2a42015-04-27 13:32:52 +0200659 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000660
Erik Språngf7c57762015-12-04 10:40:35 +0100661 if (!tmmbr_send_)
662 return nullptr;
sprang81a3e602015-08-21 05:30:11 -0700663
Erik Språngf7c57762015-12-04 10:40:35 +0100664 rtcp::Tmmbr* tmmbr = new rtcp::Tmmbr();
665 tmmbr->From(ssrc_);
666 tmmbr->To(remote_ssrc_);
667 tmmbr->WithBitrateKbps(tmmbr_send_);
668 tmmbr->WithOverhead(packet_oh_send_);
669
670 return rtc::scoped_ptr<rtcp::Tmmbr>(tmmbr);
Erik Språng61be2a42015-04-27 13:32:52 +0200671}
672
Erik Språngf7c57762015-12-04 10:40:35 +0100673rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBN(
674 const RtcpContext& ctx) {
Erik Språng242e22b2015-05-11 10:17:43 +0200675 TMMBRSet* boundingSet = tmmbr_help_.BoundingSetToSend();
Erik Språngf7c57762015-12-04 10:40:35 +0100676 if (boundingSet == nullptr)
677 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200678
Erik Språngf7c57762015-12-04 10:40:35 +0100679 rtcp::Tmmbn* tmmbn = new rtcp::Tmmbn();
680 tmmbn->From(ssrc_);
sprangd83df502015-08-27 01:05:08 -0700681 for (uint32_t i = 0; i < boundingSet->lengthOfSet(); i++) {
682 if (boundingSet->Tmmbr(i) > 0) {
Erik Språngf7c57762015-12-04 10:40:35 +0100683 tmmbn->WithTmmbr(boundingSet->Ssrc(i), boundingSet->Tmmbr(i),
684 boundingSet->PacketOH(i));
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000685 }
Erik Språng61be2a42015-04-27 13:32:52 +0200686 }
sprangd83df502015-08-27 01:05:08 -0700687
Erik Språngf7c57762015-12-04 10:40:35 +0100688 return rtc::scoped_ptr<rtcp::Tmmbn>(tmmbn);
niklase@google.com470e71d2011-07-07 08:21:25 +0000689}
690
Erik Språngf7c57762015-12-04 10:40:35 +0100691rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildAPP(const RtcpContext& ctx) {
692 rtcp::App* app = new rtcp::App();
693 app->From(ssrc_);
694 app->WithSubType(app_sub_type_);
695 app->WithName(app_name_);
696 app->WithData(app_data_.get(), app_length_);
Erik Språng521875a2015-09-01 10:11:16 +0200697
Erik Språngf7c57762015-12-04 10:40:35 +0100698 return rtc::scoped_ptr<rtcp::App>(app);
Erik Språng61be2a42015-04-27 13:32:52 +0200699}
700
Erik Språngf7c57762015-12-04 10:40:35 +0100701rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildNACK(
702 const RtcpContext& ctx) {
703 rtcp::Nack* nack = new rtcp::Nack();
704 nack->From(ssrc_);
705 nack->To(remote_ssrc_);
706 nack->WithList(ctx.nack_list_, ctx.nack_size_);
Erik Språng61be2a42015-04-27 13:32:52 +0200707
708 // Report stats.
709 NACKStringBuilder stringBuilder;
Erik Språngf7c57762015-12-04 10:40:35 +0100710 for (int idx = 0; idx < ctx.nack_size_; ++idx) {
711 stringBuilder.PushNACK(ctx.nack_list_[idx]);
712 nack_stats_.ReportRequest(ctx.nack_list_[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +0200713 }
Erik Språng61be2a42015-04-27 13:32:52 +0200714 packet_type_counter_.nack_requests = nack_stats_.requests();
715 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +0200716
717 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
718 "RTCPSender::NACK", "nacks",
719 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
720 ++packet_type_counter_.nack_packets;
721 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
722 ssrc_, packet_type_counter_.nack_packets);
723
Erik Språngf7c57762015-12-04 10:40:35 +0100724 return rtc::scoped_ptr<rtcp::Nack>(nack);
Erik Språng61be2a42015-04-27 13:32:52 +0200725}
726
Erik Språngf7c57762015-12-04 10:40:35 +0100727rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildBYE(const RtcpContext& ctx) {
728 rtcp::Bye* bye = new rtcp::Bye();
729 bye->From(ssrc_);
sprangd8ee4f92015-08-24 03:25:19 -0700730 for (uint32_t csrc : csrcs_)
Erik Språngf7c57762015-12-04 10:40:35 +0100731 bye->WithCsrc(csrc);
sprangd8ee4f92015-08-24 03:25:19 -0700732
Erik Språngf7c57762015-12-04 10:40:35 +0100733 return rtc::scoped_ptr<rtcp::Bye>(bye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000734}
735
Erik Språngf7c57762015-12-04 10:40:35 +0100736rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildReceiverReferenceTime(
737 const RtcpContext& ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200738 if (last_xr_rr_.size() >= RTCP_NUMBER_OF_SR)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000739 last_xr_rr_.erase(last_xr_rr_.begin());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000740 last_xr_rr_.insert(std::pair<uint32_t, int64_t>(
Erik Språngf7c57762015-12-04 10:40:35 +0100741 RTCPUtility::MidNtp(ctx.ntp_sec_, ctx.ntp_frac_),
742 Clock::NtpToMs(ctx.ntp_sec_, ctx.ntp_frac_)));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000743
Erik Språngf7c57762015-12-04 10:40:35 +0100744 rtcp::Xr* xr = new rtcp::Xr();
745 xr->From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000746
Erik Språngca28fdc2015-08-31 14:00:50 +0200747 rtcp::Rrtr rrtr;
Danil Chapovalovfc47ed62015-12-07 14:46:35 +0100748 rrtr.WithNtp(NtpTime(ctx.ntp_sec_, ctx.ntp_frac_));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000749
Erik Språngf7c57762015-12-04 10:40:35 +0100750 xr->WithRrtr(&rrtr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000751
Erik Språngca28fdc2015-08-31 14:00:50 +0200752 // TODO(sprang): Merge XR report sending to contain all of RRTR, DLRR, VOIP?
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000753
Erik Språngf7c57762015-12-04 10:40:35 +0100754 return rtc::scoped_ptr<rtcp::Xr>(xr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000755}
756
Erik Språngf7c57762015-12-04 10:40:35 +0100757rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildDlrr(
758 const RtcpContext& ctx) {
759 rtcp::Xr* xr = new rtcp::Xr();
760 xr->From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000761
Erik Språngca28fdc2015-08-31 14:00:50 +0200762 rtcp::Dlrr dlrr;
Erik Språngf7c57762015-12-04 10:40:35 +0100763 const RtcpReceiveTimeInfo& info = ctx.feedback_state_.last_xr_rr;
Erik Språngca28fdc2015-08-31 14:00:50 +0200764 dlrr.WithDlrrItem(info.sourceSSRC, info.lastRR, info.delaySinceLastRR);
765
Erik Språngf7c57762015-12-04 10:40:35 +0100766 xr->WithDlrr(&dlrr);
Erik Språngca28fdc2015-08-31 14:00:50 +0200767
Erik Språngf7c57762015-12-04 10:40:35 +0100768 return rtc::scoped_ptr<rtcp::Xr>(xr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000769}
770
Erik Språng242e22b2015-05-11 10:17:43 +0200771// TODO(sprang): Add a unit test for this, or remove if the code isn't used.
Erik Språngf7c57762015-12-04 10:40:35 +0100772rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildVoIPMetric(
773 const RtcpContext& context) {
774 rtcp::Xr* xr = new rtcp::Xr();
775 xr->From(ssrc_);
Erik Språngca28fdc2015-08-31 14:00:50 +0200776
777 rtcp::VoipMetric voip;
778 voip.To(remote_ssrc_);
danilchap91941ae2015-12-15 07:06:36 -0800779 voip.WithVoipMetric(xr_voip_metric_);
Erik Språngca28fdc2015-08-31 14:00:50 +0200780
Erik Språngf7c57762015-12-04 10:40:35 +0100781 xr->WithVoipMetric(&voip);
Erik Språngca28fdc2015-08-31 14:00:50 +0200782
Erik Språngf7c57762015-12-04 10:40:35 +0100783 return rtc::scoped_ptr<rtcp::Xr>(xr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000784}
785
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000786int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200787 RTCPPacketType packetType,
788 int32_t nack_size,
789 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000790 bool repeat,
791 uint64_t pictureID) {
Erik Språng242e22b2015-05-11 10:17:43 +0200792 return SendCompoundRTCP(
793 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
794 nack_size, nack_list, repeat, pictureID);
795}
796
797int32_t RTCPSender::SendCompoundRTCP(
798 const FeedbackState& feedback_state,
Erik Språngf7c57762015-12-04 10:40:35 +0100799 const std::set<RTCPPacketType>& packet_types,
Erik Språng242e22b2015-05-11 10:17:43 +0200800 int32_t nack_size,
801 const uint16_t* nack_list,
802 bool repeat,
803 uint64_t pictureID) {
Erik Språngf7c57762015-12-04 10:40:35 +0100804 PacketContainer container(transport_);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000805 {
Erik Språng242e22b2015-05-11 10:17:43 +0200806 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
pbosda903ea2015-10-02 02:36:56 -0700807 if (method_ == RtcpMode::kOff) {
Erik Språng61be2a42015-04-27 13:32:52 +0200808 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
809 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +0000810 }
Erik Språngf7c57762015-12-04 10:40:35 +0100811
812 // We need to send our NTP even if we haven't received any reports.
813 uint32_t ntp_sec;
814 uint32_t ntp_frac;
815 clock_->CurrentNtp(ntp_sec, ntp_frac);
816 RtcpContext context(feedback_state, nack_size, nack_list, repeat, pictureID,
817 ntp_sec, ntp_frac, &container);
818
819 PrepareReport(packet_types, feedback_state);
820
821 auto it = report_flags_.begin();
822 while (it != report_flags_.end()) {
823 auto builder_it = builders_.find(it->type);
824 RTC_DCHECK(builder_it != builders_.end());
825 if (it->is_volatile) {
826 report_flags_.erase(it++);
827 } else {
828 ++it;
829 }
830
831 BuilderFunc func = builder_it->second;
832 rtc::scoped_ptr<rtcp::RtcpPacket> packet = (this->*func)(context);
833 if (packet.get() == nullptr)
834 return -1;
835 container.Append(packet.release());
836 }
837
838 if (packet_type_counter_observer_ != nullptr) {
839 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
840 remote_ssrc_, packet_type_counter_);
841 }
842
843 RTC_DCHECK(AllVolatileFlagsConsumed());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000844 }
Erik Språng61be2a42015-04-27 13:32:52 +0200845
Erik Språngf7c57762015-12-04 10:40:35 +0100846 size_t bytes_sent = container.SendPackets();
847 return bytes_sent == 0 ? -1 : 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000848}
849
Erik Språngf7c57762015-12-04 10:40:35 +0100850void RTCPSender::PrepareReport(const std::set<RTCPPacketType>& packetTypes,
851 const FeedbackState& feedback_state) {
Erik Språng242e22b2015-05-11 10:17:43 +0200852 // Add all flags as volatile. Non volatile entries will not be overwritten
853 // and all new volatile flags added will be consumed by the end of this call.
854 SetFlags(packetTypes, true);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000855
Erik Språng61be2a42015-04-27 13:32:52 +0200856 if (packet_type_counter_.first_packet_time_ms == -1)
Erik Språng242e22b2015-05-11 10:17:43 +0200857 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språng61be2a42015-04-27 13:32:52 +0200858
Erik Språng242e22b2015-05-11 10:17:43 +0200859 bool generate_report;
860 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
861 // Report type already explicitly set, don't automatically populate.
862 generate_report = true;
henrikg91d6ede2015-09-17 00:24:34 -0700863 RTC_DCHECK(ConsumeFlag(kRtcpReport) == false);
Erik Språng242e22b2015-05-11 10:17:43 +0200864 } else {
865 generate_report =
pbosda903ea2015-10-02 02:36:56 -0700866 (ConsumeFlag(kRtcpReport) && method_ == RtcpMode::kReducedSize) ||
867 method_ == RtcpMode::kCompound;
Erik Språng242e22b2015-05-11 10:17:43 +0200868 if (generate_report)
869 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000870 }
871
Erik Språng0ea42d32015-06-25 14:46:16 +0200872 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
Erik Språng242e22b2015-05-11 10:17:43 +0200873 SetFlag(kRtcpSdes, true);
874
Erik Språng242e22b2015-05-11 10:17:43 +0200875 if (generate_report) {
876 if (!sending_ && xr_send_receiver_reference_time_enabled_)
877 SetFlag(kRtcpXrReceiverReferenceTime, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200878 if (feedback_state.has_last_xr_rr)
Erik Språng242e22b2015-05-11 10:17:43 +0200879 SetFlag(kRtcpXrDlrrReportBlock, true);
880
881 // generate next time to send an RTCP report
danilchap47a740b2015-12-15 00:30:07 -0800882 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000883
danilchap47a740b2015-12-15 00:30:07 -0800884 if (!audio_) {
Erik Språng242e22b2015-05-11 10:17:43 +0200885 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200886 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
887 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
888 if (send_bitrate_kbit != 0)
889 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000890 }
Erik Språng61be2a42015-04-27 13:32:52 +0200891 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
892 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
Erik Språng61be2a42015-04-27 13:32:52 +0200893 }
danilchap47a740b2015-12-15 00:30:07 -0800894 // The interval between RTCP packets is varied randomly over the
895 // range [1/2,3/2] times the calculated interval.
896 uint32_t timeToNext =
897 random_.Rand(minIntervalMs * 1 / 2, minIntervalMs * 3 / 2);
Erik Språng242e22b2015-05-11 10:17:43 +0200898 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000899
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000900 StatisticianMap statisticians =
901 receive_statistics_->GetActiveStatisticians();
danilchapa72e7342015-12-22 08:07:45 -0800902 RTC_DCHECK(report_blocks_.empty());
903 for (auto& it : statisticians) {
904 AddReportBlock(feedback_state, it.first, it.second);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000905 }
906 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000907}
908
danilchapa72e7342015-12-22 08:07:45 -0800909bool RTCPSender::AddReportBlock(const FeedbackState& feedback_state,
910 uint32_t ssrc,
911 StreamStatistician* statistician) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000912 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000913 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000914 if (!statistician->GetStatistics(&stats, true))
915 return false;
danilchapa72e7342015-12-22 08:07:45 -0800916
917 if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) {
918 LOG(LS_WARNING) << "Too many report blocks.";
919 return false;
920 }
921 RTC_DCHECK(report_blocks_.find(ssrc) == report_blocks_.end());
922 rtcp::ReportBlock* block = &report_blocks_[ssrc];
923 block->To(ssrc);
924 block->WithFractionLost(stats.fraction_lost);
925 if (!block->WithCumulativeLost(stats.cumulative_lost)) {
926 report_blocks_.erase(ssrc);
927 LOG(LS_WARNING) << "Cumulative lost is oversized.";
928 return false;
929 }
930 block->WithExtHighestSeqNum(stats.extended_max_sequence_number);
931 block->WithJitter(stats.jitter);
932 block->WithLastSr(feedback_state.remote_sr);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000933
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200934 // TODO(sprang): Do we really need separate time stamps for each report?
935 // Get our NTP as late as possible to avoid a race.
936 uint32_t ntp_secs;
937 uint32_t ntp_frac;
938 clock_->CurrentNtp(ntp_secs, ntp_frac);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000939
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200940 // Delay since last received report.
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000941 if ((feedback_state.last_rr_ntp_secs != 0) ||
942 (feedback_state.last_rr_ntp_frac != 0)) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200943 // Get the 16 lowest bits of seconds and the 16 highest bits of fractions.
944 uint32_t now = ntp_secs & 0x0000FFFF;
Erik Språng61be2a42015-04-27 13:32:52 +0200945 now <<= 16;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200946 now += (ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000947
Erik Språng61be2a42015-04-27 13:32:52 +0200948 uint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
949 receiveTime <<= 16;
950 receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000951
danilchapa72e7342015-12-22 08:07:45 -0800952 block->WithDelayLastSr(now - receiveTime);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000953 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000954 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000955}
956
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000957void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
958 assert(csrcs.size() <= kRtpCsrcSize);
Erik Språng242e22b2015-05-11 10:17:43 +0200959 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000960 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +0000961}
962
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000963int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
964 uint32_t name,
965 const uint8_t* data,
966 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +0200967 if (length % 4 != 0) {
968 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
969 return -1;
970 }
Erik Språng242e22b2015-05-11 10:17:43 +0200971 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000972
Erik Språng242e22b2015-05-11 10:17:43 +0200973 SetFlag(kRtcpApp, true);
974 app_sub_type_ = subType;
975 app_name_ = name;
976 app_data_.reset(new uint8_t[length]);
977 app_length_ = length;
978 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +0200979 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000980}
981
Erik Språng61be2a42015-04-27 13:32:52 +0200982int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
Erik Språng242e22b2015-05-11 10:17:43 +0200983 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
984 memcpy(&xr_voip_metric_, VoIPMetric, sizeof(RTCPVoIPMetric));
niklase@google.com470e71d2011-07-07 08:21:25 +0000985
Erik Språng242e22b2015-05-11 10:17:43 +0200986 SetFlag(kRtcpXrVoipMetric, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200987 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000988}
989
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000990void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200991 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
992 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000993}
994
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000995bool RTCPSender::RtcpXrReceiverReferenceTime() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200996 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
997 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000998}
999
niklase@google.com470e71d2011-07-07 08:21:25 +00001000// no callbacks allowed inside this function
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001001int32_t RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
1002 uint32_t maxBitrateKbit) {
Erik Språng242e22b2015-05-11 10:17:43 +02001003 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +00001004
Erik Språng242e22b2015-05-11 10:17:43 +02001005 if (0 == tmmbr_help_.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit)) {
1006 SetFlag(kRtcpTmmbn, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001007 return 0;
1008 }
1009 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001010}
Erik Språng61be2a42015-04-27 13:32:52 +02001011
Erik Språng242e22b2015-05-11 10:17:43 +02001012void RTCPSender::SetFlag(RTCPPacketType type, bool is_volatile) {
1013 report_flags_.insert(ReportFlag(type, is_volatile));
1014}
1015
1016void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
1017 bool is_volatile) {
1018 for (RTCPPacketType type : types)
1019 SetFlag(type, is_volatile);
1020}
1021
1022bool RTCPSender::IsFlagPresent(RTCPPacketType type) const {
1023 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
1024}
1025
1026bool RTCPSender::ConsumeFlag(RTCPPacketType type, bool forced) {
1027 auto it = report_flags_.find(ReportFlag(type, false));
1028 if (it == report_flags_.end())
1029 return false;
1030 if (it->is_volatile || forced)
1031 report_flags_.erase((it));
1032 return true;
1033}
1034
1035bool RTCPSender::AllVolatileFlagsConsumed() const {
1036 for (const ReportFlag& flag : report_flags_) {
1037 if (flag.is_volatile)
1038 return false;
1039 }
1040 return true;
1041}
1042
sprang233bd872015-09-08 13:25:16 -07001043bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
sprang233bd872015-09-08 13:25:16 -07001044 class Sender : public rtcp::RtcpPacket::PacketReadyCallback {
1045 public:
danilchap6db6cdc2015-12-15 02:54:47 -08001046 explicit Sender(Transport* transport)
Peter Boströmac547a62015-09-17 23:03:57 +02001047 : transport_(transport), send_failure_(false) {}
sprang233bd872015-09-08 13:25:16 -07001048
1049 void OnPacketReady(uint8_t* data, size_t length) override {
pbos2d566682015-09-28 09:59:31 -07001050 if (!transport_->SendRtcp(data, length))
sprang233bd872015-09-08 13:25:16 -07001051 send_failure_ = true;
1052 }
1053
1054 Transport* const transport_;
sprang233bd872015-09-08 13:25:16 -07001055 bool send_failure_;
sprang86fd9ed2015-09-29 04:45:43 -07001056 } sender(transport_);
sprang233bd872015-09-08 13:25:16 -07001057
1058 uint8_t buffer[IP_PACKET_SIZE];
1059 return packet.BuildExternalBuffer(buffer, IP_PACKET_SIZE, &sender) &&
1060 !sender.send_failure_;
1061}
1062
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001063} // namespace webrtc