blob: a5fccebad1dd67eb792fcf70ae402fafdcac5700 [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
stefan@webrtc.org9354cc92012-06-07 08:10:14 +000013#include <string.h> // memcpy
niklase@google.com470e71d2011-07-07 08:21:25 +000014
Erik Språng61be2a42015-04-27 13:32:52 +020015#include "webrtc/base/checks.h"
Peter Boströmebc0b4e2015-10-28 16:39:33 +010016#include "webrtc/base/logging.h"
tommie4f96502015-10-20 23:00:48 -070017#include "webrtc/base/trace_event.h"
terelius429c3452016-01-21 05:42:04 -080018#include "webrtc/call.h"
19#include "webrtc/call/rtc_event_log.h"
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000020#include "webrtc/common_types.h"
danilchap0219c9b2015-11-18 05:56:53 -080021#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/app.h"
danilchap50c51362015-11-22 09:03:11 -080022#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/bye.h"
danilchap2f7dea12016-01-13 02:03:04 -080023#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/compound_packet.h"
Danil Chapovalov256e5b22016-01-15 14:16:24 +010024#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_reports.h"
Danil Chapovalov5679da12016-01-15 13:19:53 +010025#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/fir.h"
danilchapa8890a52015-12-22 03:43:04 -080026#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/nack.h"
danilchapf8385ad2015-11-27 05:36:09 -080027#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/pli.h"
Danil Chapovalov97f7e132015-12-04 16:13:30 +010028#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
Danil Chapovalova5eba6c2016-01-15 12:40:15 +010029#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/remb.h"
Danil Chapovalov2c132972016-01-15 15:21:21 +010030#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rpsi.h"
Danil Chapovalov1567d0b2016-01-15 17:34:27 +010031#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sdes.h"
danilchap34ed2b92016-01-18 02:43:32 -080032#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sender_report.h"
danilchap92e677a2016-01-12 10:04:52 -080033#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sli.h"
danilchapef3d8052016-01-11 03:31:08 -080034#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbn.h"
danilchap7e8145f2016-01-11 11:49:19 -080035#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbr.h"
sprang233bd872015-09-08 13:25:16 -070036#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
tommie4f96502015-10-20 23:00:48 -070037#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.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
Erik Språng61be2a42015-04-27 13:32:52 +020041NACKStringBuilder::NACKStringBuilder()
danilchap162abd32015-12-10 02:39:40 -080042 : stream_(""), count_(0), prevNack_(0), consecutive_(false) {}
edjee@google.com79b02892013-04-04 19:43:34 +000043
pbos@webrtc.orgf3e4cee2013-07-31 15:17:19 +000044NACKStringBuilder::~NACKStringBuilder() {}
45
danilchap162abd32015-12-10 02:39:40 -080046void NACKStringBuilder::PushNACK(uint16_t nack) {
Erik Språng242e22b2015-05-11 10:17:43 +020047 if (count_ == 0) {
48 stream_ << nack;
49 } else if (nack == prevNack_ + 1) {
50 consecutive_ = true;
Erik Språng61be2a42015-04-27 13:32:52 +020051 } else {
Erik Språng242e22b2015-05-11 10:17:43 +020052 if (consecutive_) {
53 stream_ << "-" << prevNack_;
54 consecutive_ = false;
edjee@google.com79b02892013-04-04 19:43:34 +000055 }
Erik Språng242e22b2015-05-11 10:17:43 +020056 stream_ << "," << nack;
Erik Språng61be2a42015-04-27 13:32:52 +020057 }
Erik Språng242e22b2015-05-11 10:17:43 +020058 count_++;
59 prevNack_ = nack;
edjee@google.com79b02892013-04-04 19:43:34 +000060}
61
Erik Språng61be2a42015-04-27 13:32:52 +020062std::string NACKStringBuilder::GetResult() {
Erik Språng242e22b2015-05-11 10:17:43 +020063 if (consecutive_) {
64 stream_ << "-" << prevNack_;
65 consecutive_ = false;
Erik Språng61be2a42015-04-27 13:32:52 +020066 }
Erik Språng242e22b2015-05-11 10:17:43 +020067 return stream_.str();
edjee@google.com79b02892013-04-04 19:43:34 +000068}
69
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000070RTCPSender::FeedbackState::FeedbackState()
71 : send_payload_type(0),
72 frequency_hz(0),
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +000073 packets_sent(0),
74 media_bytes_sent(0),
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000075 send_bitrate(0),
76 last_rr_ntp_secs(0),
77 last_rr_ntp_frac(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000078 remote_sr(0),
Erik Språng61be2a42015-04-27 13:32:52 +020079 has_last_xr_rr(false),
danilchap162abd32015-12-10 02:39:40 -080080 module(nullptr) {}
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000081
danilchap2f7dea12016-01-13 02:03:04 -080082class PacketContainer : public rtcp::CompoundPacket,
Erik Språngf7c57762015-12-04 10:40:35 +010083 public rtcp::RtcpPacket::PacketReadyCallback {
84 public:
terelius429c3452016-01-21 05:42:04 -080085 PacketContainer(Transport* transport, RtcEventLog* event_log)
86 : transport_(transport), event_log_(event_log), bytes_sent_(0) {}
Erik Språngf7c57762015-12-04 10:40:35 +010087 virtual ~PacketContainer() {
88 for (RtcpPacket* packet : appended_packets_)
89 delete packet;
90 }
91
92 void OnPacketReady(uint8_t* data, size_t length) override {
terelius429c3452016-01-21 05:42:04 -080093 if (transport_->SendRtcp(data, length)) {
Erik Språngf7c57762015-12-04 10:40:35 +010094 bytes_sent_ += length;
terelius429c3452016-01-21 05:42:04 -080095 if (event_log_) {
96 event_log_->LogRtcpPacket(kOutgoingPacket, MediaType::ANY, data,
97 length);
98 }
99 }
Erik Språngf7c57762015-12-04 10:40:35 +0100100 }
101
102 size_t SendPackets() {
danilchap2f7dea12016-01-13 02:03:04 -0800103 rtcp::CompoundPacket::Build(this);
Erik Språngf7c57762015-12-04 10:40:35 +0100104 return bytes_sent_;
105 }
106
107 private:
108 Transport* transport_;
terelius429c3452016-01-21 05:42:04 -0800109 RtcEventLog* const event_log_;
Erik Språngf7c57762015-12-04 10:40:35 +0100110 size_t bytes_sent_;
terelius429c3452016-01-21 05:42:04 -0800111
112 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(PacketContainer);
Erik Språngf7c57762015-12-04 10:40:35 +0100113};
114
115class RTCPSender::RtcpContext {
116 public:
Erik Språng242e22b2015-05-11 10:17:43 +0200117 RtcpContext(const FeedbackState& feedback_state,
118 int32_t nack_size,
119 const uint16_t* nack_list,
120 bool repeat,
121 uint64_t picture_id,
Erik Språngf7c57762015-12-04 10:40:35 +0100122 uint32_t ntp_sec,
danilchap56036ff2016-03-22 11:14:09 -0700123 uint32_t ntp_frac)
Erik Språngf7c57762015-12-04 10:40:35 +0100124 : feedback_state_(feedback_state),
125 nack_size_(nack_size),
126 nack_list_(nack_list),
127 repeat_(repeat),
128 picture_id_(picture_id),
129 ntp_sec_(ntp_sec),
danilchap56036ff2016-03-22 11:14:09 -0700130 ntp_frac_(ntp_frac) {}
Erik Språng242e22b2015-05-11 10:17:43 +0200131
Erik Språngf7c57762015-12-04 10:40:35 +0100132 const FeedbackState& feedback_state_;
133 const int32_t nack_size_;
134 const uint16_t* nack_list_;
135 const bool repeat_;
136 const uint64_t picture_id_;
137 const uint32_t ntp_sec_;
138 const uint32_t ntp_frac_;
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,
terelius429c3452016-01-21 05:42:04 -0800146 RtcEventLog* event_log,
sprang86fd9ed2015-09-29 04:45:43 -0700147 Transport* outgoing_transport)
Peter Boströmac547a62015-09-17 23:03:57 +0200148 : audio_(audio),
Erik Språng242e22b2015-05-11 10:17:43 +0200149 clock_(clock),
danilchap47a740b2015-12-15 00:30:07 -0800150 random_(clock_->TimeInMicroseconds()),
pbosda903ea2015-10-02 02:36:56 -0700151 method_(RtcpMode::kOff),
terelius429c3452016-01-21 05:42:04 -0800152 event_log_(event_log),
sprang86fd9ed2015-09-29 04:45:43 -0700153 transport_(outgoing_transport),
Erik Språng242e22b2015-05-11 10:17:43 +0200154 using_nack_(false),
155 sending_(false),
156 remb_enabled_(false),
Erik Språng242e22b2015-05-11 10:17:43 +0200157 next_time_to_send_rtcp_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000158 start_timestamp_(0),
159 last_rtp_timestamp_(0),
160 last_frame_capture_time_ms_(-1),
Erik Språng242e22b2015-05-11 10:17:43 +0200161 ssrc_(0),
162 remote_ssrc_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000163 receive_statistics_(receive_statistics),
niklase@google.com470e71d2011-07-07 08:21:25 +0000164
Erik Språng242e22b2015-05-11 10:17:43 +0200165 sequence_number_fir_(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000166
Erik Språng242e22b2015-05-11 10:17:43 +0200167 remb_bitrate_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000168
Erik Språng242e22b2015-05-11 10:17:43 +0200169 tmmbr_help_(),
170 tmmbr_send_(0),
171 packet_oh_send_(0),
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000172
Erik Språng242e22b2015-05-11 10:17:43 +0200173 app_sub_type_(0),
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200174 app_name_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200175 app_data_(nullptr),
176 app_length_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000177
Erik Språng242e22b2015-05-11 10:17:43 +0200178 xr_send_receiver_reference_time_enabled_(false),
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000179 packet_type_counter_observer_(packet_type_counter_observer) {
sprang86fd9ed2015-09-29 04:45:43 -0700180 RTC_DCHECK(transport_ != nullptr);
Erik Språng242e22b2015-05-11 10:17:43 +0200181
182 builders_[kRtcpSr] = &RTCPSender::BuildSR;
183 builders_[kRtcpRr] = &RTCPSender::BuildRR;
Erik Språng0ea42d32015-06-25 14:46:16 +0200184 builders_[kRtcpSdes] = &RTCPSender::BuildSDES;
Erik Språng242e22b2015-05-11 10:17:43 +0200185 builders_[kRtcpPli] = &RTCPSender::BuildPLI;
186 builders_[kRtcpFir] = &RTCPSender::BuildFIR;
187 builders_[kRtcpSli] = &RTCPSender::BuildSLI;
188 builders_[kRtcpRpsi] = &RTCPSender::BuildRPSI;
189 builders_[kRtcpRemb] = &RTCPSender::BuildREMB;
190 builders_[kRtcpBye] = &RTCPSender::BuildBYE;
191 builders_[kRtcpApp] = &RTCPSender::BuildAPP;
192 builders_[kRtcpTmmbr] = &RTCPSender::BuildTMMBR;
193 builders_[kRtcpTmmbn] = &RTCPSender::BuildTMMBN;
194 builders_[kRtcpNack] = &RTCPSender::BuildNACK;
195 builders_[kRtcpXrVoipMetric] = &RTCPSender::BuildVoIPMetric;
196 builders_[kRtcpXrReceiverReferenceTime] =
197 &RTCPSender::BuildReceiverReferenceTime;
198 builders_[kRtcpXrDlrrReportBlock] = &RTCPSender::BuildDlrr;
niklase@google.com470e71d2011-07-07 08:21:25 +0000199}
200
danilchap162abd32015-12-10 02:39:40 -0800201RTCPSender::~RTCPSender() {}
niklase@google.com470e71d2011-07-07 08:21:25 +0000202
pbosda903ea2015-10-02 02:36:56 -0700203RtcpMode RTCPSender::Status() const {
danilchap56036ff2016-03-22 11:14:09 -0700204 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200205 return method_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000206}
207
pbosda903ea2015-10-02 02:36:56 -0700208void RTCPSender::SetRTCPStatus(RtcpMode method) {
danilchap56036ff2016-03-22 11:14:09 -0700209 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200210 method_ = method;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000211
pbosda903ea2015-10-02 02:36:56 -0700212 if (method == RtcpMode::kOff)
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000213 return;
Erik Språng242e22b2015-05-11 10:17:43 +0200214 next_time_to_send_rtcp_ =
215 clock_->TimeInMilliseconds() +
216 (audio_ ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000217}
218
Erik Språng61be2a42015-04-27 13:32:52 +0200219bool RTCPSender::Sending() const {
danilchap56036ff2016-03-22 11:14:09 -0700220 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200221 return sending_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000222}
223
Erik Språng61be2a42015-04-27 13:32:52 +0200224int32_t RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
225 bool sending) {
226 bool sendRTCPBye = false;
227 {
danilchap56036ff2016-03-22 11:14:09 -0700228 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000229
pbosda903ea2015-10-02 02:36:56 -0700230 if (method_ != RtcpMode::kOff) {
Erik Språng242e22b2015-05-11 10:17:43 +0200231 if (sending == false && sending_ == true) {
Erik Språng61be2a42015-04-27 13:32:52 +0200232 // Trigger RTCP bye
233 sendRTCPBye = true;
234 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000235 }
Erik Språng242e22b2015-05-11 10:17:43 +0200236 sending_ = sending;
Erik Språng61be2a42015-04-27 13:32:52 +0200237 }
238 if (sendRTCPBye)
239 return SendRTCP(feedback_state, kRtcpBye);
240 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000241}
242
Erik Språng61be2a42015-04-27 13:32:52 +0200243bool RTCPSender::REMB() const {
danilchap56036ff2016-03-22 11:14:09 -0700244 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200245 return remb_enabled_;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000246}
247
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000248void RTCPSender::SetREMBStatus(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700249 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200250 remb_enabled_ = enable;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000251}
252
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000253void RTCPSender::SetREMBData(uint32_t bitrate,
254 const std::vector<uint32_t>& ssrcs) {
danilchap56036ff2016-03-22 11:14:09 -0700255 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200256 remb_bitrate_ = bitrate;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000257 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000258
Erik Språng242e22b2015-05-11 10:17:43 +0200259 if (remb_enabled_)
260 SetFlag(kRtcpRemb, false);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000261 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
262 // throttled by the caller.
Erik Språng242e22b2015-05-11 10:17:43 +0200263 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000264}
265
Erik Språng61be2a42015-04-27 13:32:52 +0200266bool RTCPSender::TMMBR() const {
danilchap56036ff2016-03-22 11:14:09 -0700267 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200268 return IsFlagPresent(RTCPPacketType::kRtcpTmmbr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000269}
270
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000271void RTCPSender::SetTMMBRStatus(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700272 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200273 if (enable) {
274 SetFlag(RTCPPacketType::kRtcpTmmbr, false);
275 } else {
276 ConsumeFlag(RTCPPacketType::kRtcpTmmbr, true);
277 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000278}
279
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000280void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
danilchap56036ff2016-03-22 11:14:09 -0700281 rtc::CritScope lock(&critical_section_rtcp_sender_);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000282 start_timestamp_ = start_timestamp;
283}
284
285void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
286 int64_t capture_time_ms) {
danilchap56036ff2016-03-22 11:14:09 -0700287 rtc::CritScope lock(&critical_section_rtcp_sender_);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000288 last_rtp_timestamp_ = rtp_timestamp;
289 if (capture_time_ms < 0) {
290 // We don't currently get a capture time from VoiceEngine.
Erik Språng242e22b2015-05-11 10:17:43 +0200291 last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000292 } else {
293 last_frame_capture_time_ms_ = capture_time_ms;
294 }
295}
296
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000297void RTCPSender::SetSSRC(uint32_t ssrc) {
danilchap56036ff2016-03-22 11:14:09 -0700298 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000299
Erik Språng242e22b2015-05-11 10:17:43 +0200300 if (ssrc_ != 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200301 // not first SetSSRC, probably due to a collision
302 // schedule a new RTCP report
303 // make sure that we send a RTP packet
Erik Språng242e22b2015-05-11 10:17:43 +0200304 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
Erik Språng61be2a42015-04-27 13:32:52 +0200305 }
Erik Språng242e22b2015-05-11 10:17:43 +0200306 ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000307}
308
Erik Språng61be2a42015-04-27 13:32:52 +0200309void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
danilchap56036ff2016-03-22 11:14:09 -0700310 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200311 remote_ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000312}
313
Peter Boström9ba52f82015-06-01 14:12:28 +0200314int32_t RTCPSender::SetCNAME(const char* c_name) {
315 if (!c_name)
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000316 return -1;
317
henrikg91d6ede2015-09-17 00:24:34 -0700318 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
danilchap56036ff2016-03-22 11:14:09 -0700319 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200320 cname_ = c_name;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000321 return 0;
322}
323
Erik Språng0ea42d32015-06-25 14:46:16 +0200324int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC, const char* c_name) {
danilchap56036ff2016-03-22 11:14:09 -0700325 RTC_DCHECK(c_name);
henrikg91d6ede2015-09-17 00:24:34 -0700326 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
danilchap56036ff2016-03-22 11:14:09 -0700327 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200328 if (csrc_cnames_.size() >= kRtpCsrcSize)
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000329 return -1;
Erik Språng0ea42d32015-06-25 14:46:16 +0200330
331 csrc_cnames_[SSRC] = c_name;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000332 return 0;
333}
334
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000335int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
danilchap56036ff2016-03-22 11:14:09 -0700336 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200337 auto it = csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000338
Erik Språng242e22b2015-05-11 10:17:43 +0200339 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000340 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200341
Erik Språng242e22b2015-05-11 10:17:43 +0200342 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000343 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000344}
345
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000346bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
danilchap162abd32015-12-10 02:39:40 -0800347 /*
348 For audio we use a fix 5 sec interval
niklase@google.com470e71d2011-07-07 08:21:25 +0000349
danilchap162abd32015-12-10 02:39:40 -0800350 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
351 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
352 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000353
354
danilchap162abd32015-12-10 02:39:40 -0800355 From RFC 3550
niklase@google.com470e71d2011-07-07 08:21:25 +0000356
danilchap162abd32015-12-10 02:39:40 -0800357 MAX RTCP BW is 5% if the session BW
358 A send report is approximately 65 bytes inc CNAME
359 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000360
danilchap162abd32015-12-10 02:39:40 -0800361 The RECOMMENDED value for the reduced minimum in seconds is 360
362 divided by the session bandwidth in kilobits/second. This minimum
363 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
niklase@google.com470e71d2011-07-07 08:21:25 +0000364
danilchap162abd32015-12-10 02:39:40 -0800365 If the participant has not yet sent an RTCP packet (the variable
366 initial is true), the constant Tmin is set to 2.5 seconds, else it
367 is set to 5 seconds.
niklase@google.com470e71d2011-07-07 08:21:25 +0000368
danilchap162abd32015-12-10 02:39:40 -0800369 The interval between RTCP packets is varied randomly over the
370 range [0.5,1.5] times the calculated interval to avoid unintended
371 synchronization of all participants
niklase@google.com470e71d2011-07-07 08:21:25 +0000372
danilchap162abd32015-12-10 02:39:40 -0800373 if we send
374 If the participant is a sender (we_sent true), the constant C is
375 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
376 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
377 number of senders.
niklase@google.com470e71d2011-07-07 08:21:25 +0000378
danilchap162abd32015-12-10 02:39:40 -0800379 if we receive only
380 If we_sent is not true, the constant C is set
381 to the average RTCP packet size divided by 75% of the RTCP
382 bandwidth. The constant n is set to the number of receivers
383 (members - senders). If the number of senders is greater than
384 25%, senders and receivers are treated together.
niklase@google.com470e71d2011-07-07 08:21:25 +0000385
danilchap162abd32015-12-10 02:39:40 -0800386 reconsideration NOT required for peer-to-peer
387 "timer reconsideration" is
388 employed. This algorithm implements a simple back-off mechanism
389 which causes users to hold back RTCP packet transmission if the
390 group sizes are increasing.
niklase@google.com470e71d2011-07-07 08:21:25 +0000391
danilchap162abd32015-12-10 02:39:40 -0800392 n = number of members
393 C = avg_size/(rtcpBW/4)
niklase@google.com470e71d2011-07-07 08:21:25 +0000394
danilchap162abd32015-12-10 02:39:40 -0800395 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
niklase@google.com470e71d2011-07-07 08:21:25 +0000396
danilchap162abd32015-12-10 02:39:40 -0800397 4. The calculated interval T is set to a number uniformly distributed
398 between 0.5 and 1.5 times the deterministic calculated interval.
niklase@google.com470e71d2011-07-07 08:21:25 +0000399
danilchap162abd32015-12-10 02:39:40 -0800400 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
401 for the fact that the timer reconsideration algorithm converges to
402 a value of the RTCP bandwidth below the intended average
403 */
niklase@google.com470e71d2011-07-07 08:21:25 +0000404
Erik Språng242e22b2015-05-11 10:17:43 +0200405 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000406
danilchap56036ff2016-03-22 11:14:09 -0700407 rtc::CritScope lock(&critical_section_rtcp_sender_);
xians@webrtc.org8738d272011-11-25 13:43:53 +0000408
pbosda903ea2015-10-02 02:36:56 -0700409 if (method_ == RtcpMode::kOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000410 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000411
Erik Språng242e22b2015-05-11 10:17:43 +0200412 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200413 // for video key-frames we want to send the RTCP before the large key-frame
414 // if we have a 100 ms margin
415 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
416 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000417
Erik Språng242e22b2015-05-11 10:17:43 +0200418 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200419 return true;
420 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200421 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200422 // wrap
423 return true;
424 }
425 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000426}
427
danilchap56036ff2016-03-22 11:14:09 -0700428std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSR(const RtcpContext& ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200429 // The timestamp of this RTCP packet should be estimated as the timestamp of
430 // the frame being captured at this moment. We are calculating that
431 // timestamp as the last frame's timestamp + the time since the last frame
432 // was captured.
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200433 uint32_t rtp_timestamp =
434 start_timestamp_ + last_rtp_timestamp_ +
435 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) *
Erik Språngf7c57762015-12-04 10:40:35 +0100436 (ctx.feedback_state_.frequency_hz / 1000);
niklase@google.com470e71d2011-07-07 08:21:25 +0000437
Erik Språngf7c57762015-12-04 10:40:35 +0100438 rtcp::SenderReport* report = new rtcp::SenderReport();
439 report->From(ssrc_);
danilchap34ed2b92016-01-18 02:43:32 -0800440 report->WithNtp(NtpTime(ctx.ntp_sec_, ctx.ntp_frac_));
Erik Språngf7c57762015-12-04 10:40:35 +0100441 report->WithRtpTimestamp(rtp_timestamp);
442 report->WithPacketCount(ctx.feedback_state_.packets_sent);
443 report->WithOctetCount(ctx.feedback_state_.media_bytes_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000444
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200445 for (auto it : report_blocks_)
Erik Språngf7c57762015-12-04 10:40:35 +0100446 report->WithReportBlock(it.second);
niklase@google.com470e71d2011-07-07 08:21:25 +0000447
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200448 report_blocks_.clear();
Erik Språngf7c57762015-12-04 10:40:35 +0100449
danilchap56036ff2016-03-22 11:14:09 -0700450 return std::unique_ptr<rtcp::RtcpPacket>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000451}
452
danilchap56036ff2016-03-22 11:14:09 -0700453std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSDES(
Erik Språngf7c57762015-12-04 10:40:35 +0100454 const RtcpContext& ctx) {
Erik Språng0ea42d32015-06-25 14:46:16 +0200455 size_t length_cname = cname_.length();
henrikg91d6ede2015-09-17 00:24:34 -0700456 RTC_CHECK_LT(length_cname, static_cast<size_t>(RTCP_CNAME_SIZE));
niklase@google.com470e71d2011-07-07 08:21:25 +0000457
Erik Språngf7c57762015-12-04 10:40:35 +0100458 rtcp::Sdes* sdes = new rtcp::Sdes();
459 sdes->WithCName(ssrc_, cname_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200460
461 for (const auto it : csrc_cnames_)
Erik Språngf7c57762015-12-04 10:40:35 +0100462 sdes->WithCName(it.first, it.second);
Erik Språng0ea42d32015-06-25 14:46:16 +0200463
danilchap56036ff2016-03-22 11:14:09 -0700464 return std::unique_ptr<rtcp::RtcpPacket>(sdes);
niklase@google.com470e71d2011-07-07 08:21:25 +0000465}
466
danilchap56036ff2016-03-22 11:14:09 -0700467std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildRR(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100468 rtcp::ReceiverReport* report = new rtcp::ReceiverReport();
469 report->From(ssrc_);
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200470 for (auto it : report_blocks_)
Erik Språngf7c57762015-12-04 10:40:35 +0100471 report->WithReportBlock(it.second);
Erik Språng61be2a42015-04-27 13:32:52 +0200472
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200473 report_blocks_.clear();
danilchap56036ff2016-03-22 11:14:09 -0700474 return std::unique_ptr<rtcp::RtcpPacket>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000475}
476
danilchap56036ff2016-03-22 11:14:09 -0700477std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildPLI(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100478 rtcp::Pli* pli = new rtcp::Pli();
479 pli->From(ssrc_);
480 pli->To(remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200481
Erik Språng242e22b2015-05-11 10:17:43 +0200482 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
483 "RTCPSender::PLI");
484 ++packet_type_counter_.pli_packets;
485 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
486 ssrc_, packet_type_counter_.pli_packets);
487
danilchap56036ff2016-03-22 11:14:09 -0700488 return std::unique_ptr<rtcp::RtcpPacket>(pli);
Erik Språng61be2a42015-04-27 13:32:52 +0200489}
490
danilchap56036ff2016-03-22 11:14:09 -0700491std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildFIR(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100492 if (!ctx.repeat_)
sprang62dae192015-08-05 02:35:35 -0700493 ++sequence_number_fir_; // Do not increase if repetition.
niklase@google.com470e71d2011-07-07 08:21:25 +0000494
Erik Språngf7c57762015-12-04 10:40:35 +0100495 rtcp::Fir* fir = new rtcp::Fir();
496 fir->From(ssrc_);
Danil Chapovalov32e590e2016-01-22 11:04:56 +0100497 fir->WithRequestTo(remote_ssrc_, sequence_number_fir_);
Erik Språng242e22b2015-05-11 10:17:43 +0200498
499 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
500 "RTCPSender::FIR");
501 ++packet_type_counter_.fir_packets;
502 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
503 ssrc_, packet_type_counter_.fir_packets);
504
danilchap56036ff2016-03-22 11:14:09 -0700505 return std::unique_ptr<rtcp::RtcpPacket>(fir);
niklase@google.com470e71d2011-07-07 08:21:25 +0000506}
507
508/*
509 0 1 2 3
510 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
511 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
512 | First | Number | PictureID |
513 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
514*/
danilchap56036ff2016-03-22 11:14:09 -0700515std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSLI(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100516 rtcp::Sli* sli = new rtcp::Sli();
517 sli->From(ssrc_);
518 sli->To(remote_ssrc_);
sprang0365a272015-08-11 01:02:37 -0700519 // Crop picture id to 6 least significant bits.
Erik Språngf7c57762015-12-04 10:40:35 +0100520 sli->WithPictureId(ctx.picture_id_ & 0x3F);
sprang0365a272015-08-11 01:02:37 -0700521
danilchap56036ff2016-03-22 11:14:09 -0700522 return std::unique_ptr<rtcp::RtcpPacket>(sli);
niklase@google.com470e71d2011-07-07 08:21:25 +0000523}
524
525/*
526 0 1 2 3
527 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
528 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
529 | PB |0| Payload Type| Native RPSI bit string |
530 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
531 | defined per codec ... | Padding (0) |
532 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
533*/
534/*
535* Note: not generic made for VP8
536*/
danilchap56036ff2016-03-22 11:14:09 -0700537std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildRPSI(
Erik Språngf7c57762015-12-04 10:40:35 +0100538 const RtcpContext& ctx) {
539 if (ctx.feedback_state_.send_payload_type == 0xFF)
540 return nullptr;
Erik Språng242e22b2015-05-11 10:17:43 +0200541
Erik Språngf7c57762015-12-04 10:40:35 +0100542 rtcp::Rpsi* rpsi = new rtcp::Rpsi();
543 rpsi->From(ssrc_);
544 rpsi->To(remote_ssrc_);
545 rpsi->WithPayloadType(ctx.feedback_state_.send_payload_type);
546 rpsi->WithPictureId(ctx.picture_id_);
sprangcf7f54d2015-08-13 04:37:42 -0700547
danilchap56036ff2016-03-22 11:14:09 -0700548 return std::unique_ptr<rtcp::RtcpPacket>(rpsi);
niklase@google.com470e71d2011-07-07 08:21:25 +0000549}
550
danilchap56036ff2016-03-22 11:14:09 -0700551std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildREMB(
Erik Språngf7c57762015-12-04 10:40:35 +0100552 const RtcpContext& ctx) {
553 rtcp::Remb* remb = new rtcp::Remb();
554 remb->From(ssrc_);
sprangdd4edc52015-08-21 04:21:51 -0700555 for (uint32_t ssrc : remb_ssrcs_)
Erik Språngf7c57762015-12-04 10:40:35 +0100556 remb->AppliesTo(ssrc);
557 remb->WithBitrateBps(remb_bitrate_);
Erik Språng61be2a42015-04-27 13:32:52 +0200558
Erik Språng242e22b2015-05-11 10:17:43 +0200559 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
560 "RTCPSender::REMB");
561
danilchap56036ff2016-03-22 11:14:09 -0700562 return std::unique_ptr<rtcp::RtcpPacket>(remb);
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000563}
564
Erik Språng61be2a42015-04-27 13:32:52 +0200565void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
danilchap56036ff2016-03-22 11:14:09 -0700566 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200567 tmmbr_send_ = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000568}
569
danilchap56036ff2016-03-22 11:14:09 -0700570std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBR(
Erik Språngf7c57762015-12-04 10:40:35 +0100571 const RtcpContext& ctx) {
572 if (ctx.feedback_state_.module == nullptr)
573 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200574 // Before sending the TMMBR check the received TMMBN, only an owner is
575 // allowed to raise the bitrate:
576 // * If the sender is an owner of the TMMBN -> send TMMBR
577 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000578
Erik Språng61be2a42015-04-27 13:32:52 +0200579 // get current bounding set from RTCP receiver
580 bool tmmbrOwner = false;
581 // store in candidateSet, allocates one extra slot
Erik Språng242e22b2015-05-11 10:17:43 +0200582 TMMBRSet* candidateSet = tmmbr_help_.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000583
Erik Språng242e22b2015-05-11 10:17:43 +0200584 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
585 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
Erik Språng61be2a42015-04-27 13:32:52 +0200586 // since RTCPreceiver is not doing the reverse we should be fine
587 int32_t lengthOfBoundingSet =
danilchap6db6cdc2015-12-15 02:54:47 -0800588 ctx.feedback_state_.module->BoundingSet(&tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +0000589
Erik Språng61be2a42015-04-27 13:32:52 +0200590 if (lengthOfBoundingSet > 0) {
591 for (int32_t i = 0; i < lengthOfBoundingSet; i++) {
Erik Språng242e22b2015-05-11 10:17:43 +0200592 if (candidateSet->Tmmbr(i) == tmmbr_send_ &&
593 candidateSet->PacketOH(i) == packet_oh_send_) {
Erik Språngf7c57762015-12-04 10:40:35 +0100594 // Do not send the same tuple.
595 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200596 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000597 }
Erik Språng61be2a42015-04-27 13:32:52 +0200598 if (!tmmbrOwner) {
599 // use received bounding set as candidate set
600 // add current tuple
Erik Språng242e22b2015-05-11 10:17:43 +0200601 candidateSet->SetEntry(lengthOfBoundingSet, tmmbr_send_, packet_oh_send_,
602 ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200603 int numCandidates = lengthOfBoundingSet + 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000604
Erik Språng61be2a42015-04-27 13:32:52 +0200605 // find bounding set
Erik Språngf7c57762015-12-04 10:40:35 +0100606 TMMBRSet* boundingSet = nullptr;
Erik Språng242e22b2015-05-11 10:17:43 +0200607 int numBoundingSet = tmmbr_help_.FindTMMBRBoundingSet(boundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200608 if (numBoundingSet > 0 || numBoundingSet <= numCandidates)
Erik Språng242e22b2015-05-11 10:17:43 +0200609 tmmbrOwner = tmmbr_help_.IsOwner(ssrc_, numBoundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200610 if (!tmmbrOwner) {
Erik Språngf7c57762015-12-04 10:40:35 +0100611 // Did not enter bounding set, no meaning to send this request.
612 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200613 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000614 }
Erik Språng61be2a42015-04-27 13:32:52 +0200615 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000616
Erik Språngf7c57762015-12-04 10:40:35 +0100617 if (!tmmbr_send_)
618 return nullptr;
sprang81a3e602015-08-21 05:30:11 -0700619
Erik Språngf7c57762015-12-04 10:40:35 +0100620 rtcp::Tmmbr* tmmbr = new rtcp::Tmmbr();
621 tmmbr->From(ssrc_);
danilchapf174e3a2016-02-05 04:56:36 -0800622 rtcp::TmmbItem request;
623 request.set_ssrc(remote_ssrc_);
624 request.set_bitrate_bps(tmmbr_send_ * 1000);
625 request.set_packet_overhead(packet_oh_send_);
626 tmmbr->WithTmmbr(request);
Erik Språngf7c57762015-12-04 10:40:35 +0100627
danilchap56036ff2016-03-22 11:14:09 -0700628 return std::unique_ptr<rtcp::RtcpPacket>(tmmbr);
Erik Språng61be2a42015-04-27 13:32:52 +0200629}
630
danilchap56036ff2016-03-22 11:14:09 -0700631std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBN(
Erik Språngf7c57762015-12-04 10:40:35 +0100632 const RtcpContext& ctx) {
Erik Språng242e22b2015-05-11 10:17:43 +0200633 TMMBRSet* boundingSet = tmmbr_help_.BoundingSetToSend();
Erik Språngf7c57762015-12-04 10:40:35 +0100634 if (boundingSet == nullptr)
635 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200636
Erik Språngf7c57762015-12-04 10:40:35 +0100637 rtcp::Tmmbn* tmmbn = new rtcp::Tmmbn();
638 tmmbn->From(ssrc_);
sprangd83df502015-08-27 01:05:08 -0700639 for (uint32_t i = 0; i < boundingSet->lengthOfSet(); i++) {
640 if (boundingSet->Tmmbr(i) > 0) {
Erik Språngf7c57762015-12-04 10:40:35 +0100641 tmmbn->WithTmmbr(boundingSet->Ssrc(i), boundingSet->Tmmbr(i),
642 boundingSet->PacketOH(i));
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000643 }
Erik Språng61be2a42015-04-27 13:32:52 +0200644 }
sprangd83df502015-08-27 01:05:08 -0700645
danilchap56036ff2016-03-22 11:14:09 -0700646 return std::unique_ptr<rtcp::RtcpPacket>(tmmbn);
niklase@google.com470e71d2011-07-07 08:21:25 +0000647}
648
danilchap56036ff2016-03-22 11:14:09 -0700649std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildAPP(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100650 rtcp::App* app = new rtcp::App();
651 app->From(ssrc_);
652 app->WithSubType(app_sub_type_);
653 app->WithName(app_name_);
654 app->WithData(app_data_.get(), app_length_);
Erik Språng521875a2015-09-01 10:11:16 +0200655
danilchap56036ff2016-03-22 11:14:09 -0700656 return std::unique_ptr<rtcp::RtcpPacket>(app);
Erik Språng61be2a42015-04-27 13:32:52 +0200657}
658
danilchap56036ff2016-03-22 11:14:09 -0700659std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildNACK(
Erik Språngf7c57762015-12-04 10:40:35 +0100660 const RtcpContext& ctx) {
661 rtcp::Nack* nack = new rtcp::Nack();
662 nack->From(ssrc_);
663 nack->To(remote_ssrc_);
664 nack->WithList(ctx.nack_list_, ctx.nack_size_);
Erik Språng61be2a42015-04-27 13:32:52 +0200665
666 // Report stats.
667 NACKStringBuilder stringBuilder;
Erik Språngf7c57762015-12-04 10:40:35 +0100668 for (int idx = 0; idx < ctx.nack_size_; ++idx) {
669 stringBuilder.PushNACK(ctx.nack_list_[idx]);
670 nack_stats_.ReportRequest(ctx.nack_list_[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +0200671 }
Erik Språng61be2a42015-04-27 13:32:52 +0200672 packet_type_counter_.nack_requests = nack_stats_.requests();
673 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +0200674
675 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
676 "RTCPSender::NACK", "nacks",
677 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
678 ++packet_type_counter_.nack_packets;
679 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
680 ssrc_, packet_type_counter_.nack_packets);
681
danilchap56036ff2016-03-22 11:14:09 -0700682 return std::unique_ptr<rtcp::RtcpPacket>(nack);
Erik Språng61be2a42015-04-27 13:32:52 +0200683}
684
danilchap56036ff2016-03-22 11:14:09 -0700685std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildBYE(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100686 rtcp::Bye* bye = new rtcp::Bye();
687 bye->From(ssrc_);
sprangd8ee4f92015-08-24 03:25:19 -0700688 for (uint32_t csrc : csrcs_)
Erik Språngf7c57762015-12-04 10:40:35 +0100689 bye->WithCsrc(csrc);
sprangd8ee4f92015-08-24 03:25:19 -0700690
danilchap56036ff2016-03-22 11:14:09 -0700691 return std::unique_ptr<rtcp::RtcpPacket>(bye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000692}
693
danilchap56036ff2016-03-22 11:14:09 -0700694std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildReceiverReferenceTime(
Erik Språngf7c57762015-12-04 10:40:35 +0100695 const RtcpContext& ctx) {
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000696
Danil Chapovalov256e5b22016-01-15 14:16:24 +0100697 rtcp::ExtendedReports* xr = new rtcp::ExtendedReports();
Erik Språngf7c57762015-12-04 10:40:35 +0100698 xr->From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000699
Erik Språngca28fdc2015-08-31 14:00:50 +0200700 rtcp::Rrtr rrtr;
Danil Chapovalovfc47ed62015-12-07 14:46:35 +0100701 rrtr.WithNtp(NtpTime(ctx.ntp_sec_, ctx.ntp_frac_));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000702
danilchapde138822016-01-29 11:26:14 -0800703 xr->WithRrtr(rrtr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000704
Erik Språngca28fdc2015-08-31 14:00:50 +0200705 // TODO(sprang): Merge XR report sending to contain all of RRTR, DLRR, VOIP?
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000706
danilchap56036ff2016-03-22 11:14:09 -0700707 return std::unique_ptr<rtcp::RtcpPacket>(xr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000708}
709
danilchap56036ff2016-03-22 11:14:09 -0700710std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildDlrr(
Erik Språngf7c57762015-12-04 10:40:35 +0100711 const RtcpContext& ctx) {
Danil Chapovalov256e5b22016-01-15 14:16:24 +0100712 rtcp::ExtendedReports* xr = new rtcp::ExtendedReports();
Erik Språngf7c57762015-12-04 10:40:35 +0100713 xr->From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000714
Erik Språngca28fdc2015-08-31 14:00:50 +0200715 rtcp::Dlrr dlrr;
Erik Språngf7c57762015-12-04 10:40:35 +0100716 const RtcpReceiveTimeInfo& info = ctx.feedback_state_.last_xr_rr;
Erik Språngca28fdc2015-08-31 14:00:50 +0200717 dlrr.WithDlrrItem(info.sourceSSRC, info.lastRR, info.delaySinceLastRR);
718
danilchapde138822016-01-29 11:26:14 -0800719 xr->WithDlrr(dlrr);
Erik Språngca28fdc2015-08-31 14:00:50 +0200720
danilchap56036ff2016-03-22 11:14:09 -0700721 return std::unique_ptr<rtcp::RtcpPacket>(xr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000722}
723
Erik Språng242e22b2015-05-11 10:17:43 +0200724// TODO(sprang): Add a unit test for this, or remove if the code isn't used.
danilchap56036ff2016-03-22 11:14:09 -0700725std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildVoIPMetric(
Erik Språngf7c57762015-12-04 10:40:35 +0100726 const RtcpContext& context) {
Danil Chapovalov256e5b22016-01-15 14:16:24 +0100727 rtcp::ExtendedReports* xr = new rtcp::ExtendedReports();
Erik Språngf7c57762015-12-04 10:40:35 +0100728 xr->From(ssrc_);
Erik Språngca28fdc2015-08-31 14:00:50 +0200729
730 rtcp::VoipMetric voip;
731 voip.To(remote_ssrc_);
danilchap91941ae2015-12-15 07:06:36 -0800732 voip.WithVoipMetric(xr_voip_metric_);
Erik Språngca28fdc2015-08-31 14:00:50 +0200733
danilchapde138822016-01-29 11:26:14 -0800734 xr->WithVoipMetric(voip);
Erik Språngca28fdc2015-08-31 14:00:50 +0200735
danilchap56036ff2016-03-22 11:14:09 -0700736 return std::unique_ptr<rtcp::RtcpPacket>(xr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000737}
738
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000739int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200740 RTCPPacketType packetType,
741 int32_t nack_size,
742 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000743 bool repeat,
744 uint64_t pictureID) {
Erik Språng242e22b2015-05-11 10:17:43 +0200745 return SendCompoundRTCP(
746 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
747 nack_size, nack_list, repeat, pictureID);
748}
749
750int32_t RTCPSender::SendCompoundRTCP(
751 const FeedbackState& feedback_state,
Erik Språngf7c57762015-12-04 10:40:35 +0100752 const std::set<RTCPPacketType>& packet_types,
Erik Språng242e22b2015-05-11 10:17:43 +0200753 int32_t nack_size,
754 const uint16_t* nack_list,
755 bool repeat,
756 uint64_t pictureID) {
terelius429c3452016-01-21 05:42:04 -0800757 PacketContainer container(transport_, event_log_);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000758 {
danilchap56036ff2016-03-22 11:14:09 -0700759 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbosda903ea2015-10-02 02:36:56 -0700760 if (method_ == RtcpMode::kOff) {
Erik Språng61be2a42015-04-27 13:32:52 +0200761 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
762 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +0000763 }
Erik Språngf7c57762015-12-04 10:40:35 +0100764
765 // We need to send our NTP even if we haven't received any reports.
766 uint32_t ntp_sec;
767 uint32_t ntp_frac;
768 clock_->CurrentNtp(ntp_sec, ntp_frac);
769 RtcpContext context(feedback_state, nack_size, nack_list, repeat, pictureID,
danilchap56036ff2016-03-22 11:14:09 -0700770 ntp_sec, ntp_frac);
Erik Språngf7c57762015-12-04 10:40:35 +0100771
772 PrepareReport(packet_types, feedback_state);
773
danilchap56036ff2016-03-22 11:14:09 -0700774 std::unique_ptr<rtcp::RtcpPacket> packet_bye;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800775
Erik Språngf7c57762015-12-04 10:40:35 +0100776 auto it = report_flags_.begin();
777 while (it != report_flags_.end()) {
778 auto builder_it = builders_.find(it->type);
779 RTC_DCHECK(builder_it != builders_.end());
780 if (it->is_volatile) {
781 report_flags_.erase(it++);
782 } else {
783 ++it;
784 }
785
786 BuilderFunc func = builder_it->second;
danilchap56036ff2016-03-22 11:14:09 -0700787 std::unique_ptr<rtcp::RtcpPacket> packet = (this->*func)(context);
Erik Språngf7c57762015-12-04 10:40:35 +0100788 if (packet.get() == nullptr)
789 return -1;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800790 // If there is a BYE, don't append now - save it and append it
791 // at the end later.
792 if (builder_it->first == kRtcpBye) {
793 packet_bye = std::move(packet);
794 } else {
795 container.Append(packet.release());
796 }
797 }
798
799 // Append the BYE now at the end
800 if (packet_bye) {
801 container.Append(packet_bye.release());
Erik Språngf7c57762015-12-04 10:40:35 +0100802 }
803
804 if (packet_type_counter_observer_ != nullptr) {
805 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
806 remote_ssrc_, packet_type_counter_);
807 }
808
809 RTC_DCHECK(AllVolatileFlagsConsumed());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000810 }
Erik Språng61be2a42015-04-27 13:32:52 +0200811
Erik Språngf7c57762015-12-04 10:40:35 +0100812 size_t bytes_sent = container.SendPackets();
813 return bytes_sent == 0 ? -1 : 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000814}
815
Erik Språngf7c57762015-12-04 10:40:35 +0100816void RTCPSender::PrepareReport(const std::set<RTCPPacketType>& packetTypes,
817 const FeedbackState& feedback_state) {
Erik Språng242e22b2015-05-11 10:17:43 +0200818 // Add all flags as volatile. Non volatile entries will not be overwritten
819 // and all new volatile flags added will be consumed by the end of this call.
820 SetFlags(packetTypes, true);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000821
Erik Språng61be2a42015-04-27 13:32:52 +0200822 if (packet_type_counter_.first_packet_time_ms == -1)
Erik Språng242e22b2015-05-11 10:17:43 +0200823 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språng61be2a42015-04-27 13:32:52 +0200824
Erik Språng242e22b2015-05-11 10:17:43 +0200825 bool generate_report;
826 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
827 // Report type already explicitly set, don't automatically populate.
828 generate_report = true;
henrikg91d6ede2015-09-17 00:24:34 -0700829 RTC_DCHECK(ConsumeFlag(kRtcpReport) == false);
Erik Språng242e22b2015-05-11 10:17:43 +0200830 } else {
831 generate_report =
pbosda903ea2015-10-02 02:36:56 -0700832 (ConsumeFlag(kRtcpReport) && method_ == RtcpMode::kReducedSize) ||
833 method_ == RtcpMode::kCompound;
Erik Språng242e22b2015-05-11 10:17:43 +0200834 if (generate_report)
835 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000836 }
837
Erik Språng0ea42d32015-06-25 14:46:16 +0200838 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
Erik Språng242e22b2015-05-11 10:17:43 +0200839 SetFlag(kRtcpSdes, true);
840
Erik Språng242e22b2015-05-11 10:17:43 +0200841 if (generate_report) {
842 if (!sending_ && xr_send_receiver_reference_time_enabled_)
843 SetFlag(kRtcpXrReceiverReferenceTime, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200844 if (feedback_state.has_last_xr_rr)
Erik Språng242e22b2015-05-11 10:17:43 +0200845 SetFlag(kRtcpXrDlrrReportBlock, true);
846
847 // generate next time to send an RTCP report
danilchap47a740b2015-12-15 00:30:07 -0800848 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000849
danilchap47a740b2015-12-15 00:30:07 -0800850 if (!audio_) {
Erik Språng242e22b2015-05-11 10:17:43 +0200851 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200852 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
853 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
854 if (send_bitrate_kbit != 0)
855 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000856 }
Erik Språng61be2a42015-04-27 13:32:52 +0200857 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
858 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
Erik Språng61be2a42015-04-27 13:32:52 +0200859 }
danilchap47a740b2015-12-15 00:30:07 -0800860 // The interval between RTCP packets is varied randomly over the
861 // range [1/2,3/2] times the calculated interval.
862 uint32_t timeToNext =
863 random_.Rand(minIntervalMs * 1 / 2, minIntervalMs * 3 / 2);
Erik Språng242e22b2015-05-11 10:17:43 +0200864 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000865
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000866 StatisticianMap statisticians =
867 receive_statistics_->GetActiveStatisticians();
danilchapa72e7342015-12-22 08:07:45 -0800868 RTC_DCHECK(report_blocks_.empty());
869 for (auto& it : statisticians) {
870 AddReportBlock(feedback_state, it.first, it.second);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000871 }
872 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000873}
874
danilchapa72e7342015-12-22 08:07:45 -0800875bool RTCPSender::AddReportBlock(const FeedbackState& feedback_state,
876 uint32_t ssrc,
877 StreamStatistician* statistician) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000878 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000879 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000880 if (!statistician->GetStatistics(&stats, true))
881 return false;
danilchapa72e7342015-12-22 08:07:45 -0800882
883 if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) {
884 LOG(LS_WARNING) << "Too many report blocks.";
885 return false;
886 }
887 RTC_DCHECK(report_blocks_.find(ssrc) == report_blocks_.end());
888 rtcp::ReportBlock* block = &report_blocks_[ssrc];
889 block->To(ssrc);
890 block->WithFractionLost(stats.fraction_lost);
891 if (!block->WithCumulativeLost(stats.cumulative_lost)) {
892 report_blocks_.erase(ssrc);
893 LOG(LS_WARNING) << "Cumulative lost is oversized.";
894 return false;
895 }
896 block->WithExtHighestSeqNum(stats.extended_max_sequence_number);
897 block->WithJitter(stats.jitter);
898 block->WithLastSr(feedback_state.remote_sr);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000899
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200900 // TODO(sprang): Do we really need separate time stamps for each report?
901 // Get our NTP as late as possible to avoid a race.
902 uint32_t ntp_secs;
903 uint32_t ntp_frac;
904 clock_->CurrentNtp(ntp_secs, ntp_frac);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000905
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200906 // Delay since last received report.
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000907 if ((feedback_state.last_rr_ntp_secs != 0) ||
908 (feedback_state.last_rr_ntp_frac != 0)) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200909 // Get the 16 lowest bits of seconds and the 16 highest bits of fractions.
910 uint32_t now = ntp_secs & 0x0000FFFF;
Erik Språng61be2a42015-04-27 13:32:52 +0200911 now <<= 16;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200912 now += (ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000913
Erik Språng61be2a42015-04-27 13:32:52 +0200914 uint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
915 receiveTime <<= 16;
916 receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000917
danilchapa72e7342015-12-22 08:07:45 -0800918 block->WithDelayLastSr(now - receiveTime);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000919 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000920 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000921}
922
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000923void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
danilchap56036ff2016-03-22 11:14:09 -0700924 RTC_DCHECK_LE(csrcs.size(), static_cast<size_t>(kRtpCsrcSize));
925 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000926 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +0000927}
928
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000929int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
930 uint32_t name,
931 const uint8_t* data,
932 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +0200933 if (length % 4 != 0) {
934 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
935 return -1;
936 }
danilchap56036ff2016-03-22 11:14:09 -0700937 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000938
Erik Språng242e22b2015-05-11 10:17:43 +0200939 SetFlag(kRtcpApp, true);
940 app_sub_type_ = subType;
941 app_name_ = name;
942 app_data_.reset(new uint8_t[length]);
943 app_length_ = length;
944 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +0200945 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000946}
947
Erik Språng61be2a42015-04-27 13:32:52 +0200948int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
danilchap56036ff2016-03-22 11:14:09 -0700949 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200950 memcpy(&xr_voip_metric_, VoIPMetric, sizeof(RTCPVoIPMetric));
niklase@google.com470e71d2011-07-07 08:21:25 +0000951
Erik Språng242e22b2015-05-11 10:17:43 +0200952 SetFlag(kRtcpXrVoipMetric, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200953 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000954}
955
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000956void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700957 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200958 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000959}
960
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000961bool RTCPSender::RtcpXrReceiverReferenceTime() const {
danilchap56036ff2016-03-22 11:14:09 -0700962 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200963 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000964}
965
niklase@google.com470e71d2011-07-07 08:21:25 +0000966// no callbacks allowed inside this function
Peter Boström9d0c4322016-02-16 17:59:27 +0100967int32_t RTCPSender::SetTMMBN(const TMMBRSet* boundingSet) {
danilchap56036ff2016-03-22 11:14:09 -0700968 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000969
Peter Boström9d0c4322016-02-16 17:59:27 +0100970 if (0 == tmmbr_help_.SetTMMBRBoundingSetToSend(boundingSet)) {
Erik Språng242e22b2015-05-11 10:17:43 +0200971 SetFlag(kRtcpTmmbn, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200972 return 0;
973 }
974 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000975}
Erik Språng61be2a42015-04-27 13:32:52 +0200976
Erik Språng242e22b2015-05-11 10:17:43 +0200977void RTCPSender::SetFlag(RTCPPacketType type, bool is_volatile) {
978 report_flags_.insert(ReportFlag(type, is_volatile));
979}
980
981void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
982 bool is_volatile) {
983 for (RTCPPacketType type : types)
984 SetFlag(type, is_volatile);
985}
986
987bool RTCPSender::IsFlagPresent(RTCPPacketType type) const {
988 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
989}
990
991bool RTCPSender::ConsumeFlag(RTCPPacketType type, bool forced) {
992 auto it = report_flags_.find(ReportFlag(type, false));
993 if (it == report_flags_.end())
994 return false;
995 if (it->is_volatile || forced)
996 report_flags_.erase((it));
997 return true;
998}
999
1000bool RTCPSender::AllVolatileFlagsConsumed() const {
1001 for (const ReportFlag& flag : report_flags_) {
1002 if (flag.is_volatile)
1003 return false;
1004 }
1005 return true;
1006}
1007
sprang233bd872015-09-08 13:25:16 -07001008bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
sprang233bd872015-09-08 13:25:16 -07001009 class Sender : public rtcp::RtcpPacket::PacketReadyCallback {
1010 public:
terelius429c3452016-01-21 05:42:04 -08001011 Sender(Transport* transport, RtcEventLog* event_log)
1012 : transport_(transport), event_log_(event_log), send_failure_(false) {}
sprang233bd872015-09-08 13:25:16 -07001013
1014 void OnPacketReady(uint8_t* data, size_t length) override {
terelius429c3452016-01-21 05:42:04 -08001015 if (transport_->SendRtcp(data, length)) {
1016 if (event_log_) {
1017 event_log_->LogRtcpPacket(kOutgoingPacket, MediaType::ANY, data,
1018 length);
1019 }
1020 } else {
sprang233bd872015-09-08 13:25:16 -07001021 send_failure_ = true;
terelius429c3452016-01-21 05:42:04 -08001022 }
sprang233bd872015-09-08 13:25:16 -07001023 }
1024
1025 Transport* const transport_;
terelius429c3452016-01-21 05:42:04 -08001026 RtcEventLog* const event_log_;
sprang233bd872015-09-08 13:25:16 -07001027 bool send_failure_;
terelius429c3452016-01-21 05:42:04 -08001028 // TODO(terelius): We would like to
1029 // RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(Sender);
1030 // but we can't because of an incorrect warning (C4822) in MVS 2013.
1031 } sender(transport_, event_log_);
sprang233bd872015-09-08 13:25:16 -07001032
1033 uint8_t buffer[IP_PACKET_SIZE];
1034 return packet.BuildExternalBuffer(buffer, IP_PACKET_SIZE, &sender) &&
1035 !sender.send_failure_;
1036}
1037
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001038} // namespace webrtc