blob: 9ff50fc81130623e94f6224da79d8850c00b24df [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"
Danil Chapovalov256e5b22016-01-15 14:16:24 +010028#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_reports.h"
Danil Chapovalov5679da12016-01-15 13:19:53 +010029#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/fir.h"
danilchapa8890a52015-12-22 03:43:04 -080030#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/nack.h"
danilchapf8385ad2015-11-27 05:36:09 -080031#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/pli.h"
Danil Chapovalov97f7e132015-12-04 16:13:30 +010032#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
Danil Chapovalova5eba6c2016-01-15 12:40:15 +010033#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/remb.h"
danilchap92e677a2016-01-12 10:04:52 -080034#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sli.h"
danilchapef3d8052016-01-11 03:31:08 -080035#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbn.h"
danilchap7e8145f2016-01-11 11:49:19 -080036#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbr.h"
sprang233bd872015-09-08 13:25:16 -070037#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
tommie4f96502015-10-20 23:00:48 -070038#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010039#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000040
niklase@google.com470e71d2011-07-07 08:21:25 +000041namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000042
43using RTCPUtility::RTCPCnameInformation;
44
Erik Språng61be2a42015-04-27 13:32:52 +020045NACKStringBuilder::NACKStringBuilder()
danilchap162abd32015-12-10 02:39:40 -080046 : stream_(""), count_(0), prevNack_(0), consecutive_(false) {}
edjee@google.com79b02892013-04-04 19:43:34 +000047
pbos@webrtc.orgf3e4cee2013-07-31 15:17:19 +000048NACKStringBuilder::~NACKStringBuilder() {}
49
danilchap162abd32015-12-10 02:39:40 -080050void NACKStringBuilder::PushNACK(uint16_t nack) {
Erik Språng242e22b2015-05-11 10:17:43 +020051 if (count_ == 0) {
52 stream_ << nack;
53 } else if (nack == prevNack_ + 1) {
54 consecutive_ = true;
Erik Språng61be2a42015-04-27 13:32:52 +020055 } else {
Erik Språng242e22b2015-05-11 10:17:43 +020056 if (consecutive_) {
57 stream_ << "-" << prevNack_;
58 consecutive_ = false;
edjee@google.com79b02892013-04-04 19:43:34 +000059 }
Erik Språng242e22b2015-05-11 10:17:43 +020060 stream_ << "," << nack;
Erik Språng61be2a42015-04-27 13:32:52 +020061 }
Erik Språng242e22b2015-05-11 10:17:43 +020062 count_++;
63 prevNack_ = nack;
edjee@google.com79b02892013-04-04 19:43:34 +000064}
65
Erik Språng61be2a42015-04-27 13:32:52 +020066std::string NACKStringBuilder::GetResult() {
Erik Språng242e22b2015-05-11 10:17:43 +020067 if (consecutive_) {
68 stream_ << "-" << prevNack_;
69 consecutive_ = false;
Erik Språng61be2a42015-04-27 13:32:52 +020070 }
Erik Språng242e22b2015-05-11 10:17:43 +020071 return stream_.str();
edjee@google.com79b02892013-04-04 19:43:34 +000072}
73
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000074RTCPSender::FeedbackState::FeedbackState()
75 : send_payload_type(0),
76 frequency_hz(0),
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +000077 packets_sent(0),
78 media_bytes_sent(0),
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000079 send_bitrate(0),
80 last_rr_ntp_secs(0),
81 last_rr_ntp_frac(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000082 remote_sr(0),
Erik Språng61be2a42015-04-27 13:32:52 +020083 has_last_xr_rr(false),
danilchap162abd32015-12-10 02:39:40 -080084 module(nullptr) {}
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000085
danilchap2f7dea12016-01-13 02:03:04 -080086class PacketContainer : public rtcp::CompoundPacket,
Erik Språngf7c57762015-12-04 10:40:35 +010087 public rtcp::RtcpPacket::PacketReadyCallback {
88 public:
89 explicit PacketContainer(Transport* transport)
90 : transport_(transport), bytes_sent_(0) {}
91 virtual ~PacketContainer() {
92 for (RtcpPacket* packet : appended_packets_)
93 delete packet;
94 }
95
96 void OnPacketReady(uint8_t* data, size_t length) override {
97 if (transport_->SendRtcp(data, length))
98 bytes_sent_ += length;
99 }
100
101 size_t SendPackets() {
danilchap2f7dea12016-01-13 02:03:04 -0800102 rtcp::CompoundPacket::Build(this);
Erik Språngf7c57762015-12-04 10:40:35 +0100103 return bytes_sent_;
104 }
105
106 private:
107 Transport* transport_;
108 size_t bytes_sent_;
109};
110
111class RTCPSender::RtcpContext {
112 public:
Erik Språng242e22b2015-05-11 10:17:43 +0200113 RtcpContext(const FeedbackState& feedback_state,
114 int32_t nack_size,
115 const uint16_t* nack_list,
116 bool repeat,
117 uint64_t picture_id,
Erik Språngf7c57762015-12-04 10:40:35 +0100118 uint32_t ntp_sec,
119 uint32_t ntp_frac,
120 PacketContainer* container)
121 : feedback_state_(feedback_state),
122 nack_size_(nack_size),
123 nack_list_(nack_list),
124 repeat_(repeat),
125 picture_id_(picture_id),
126 ntp_sec_(ntp_sec),
127 ntp_frac_(ntp_frac),
128 container_(container) {}
Erik Språng242e22b2015-05-11 10:17:43 +0200129
Erik Språngf7c57762015-12-04 10:40:35 +0100130 virtual ~RtcpContext() {}
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ång242e22b2015-05-11 10:17:43 +0200139
Erik Språngf7c57762015-12-04 10:40:35 +0100140 PacketContainer* const container_;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200141};
142
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000143RTCPSender::RTCPSender(
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000144 bool audio,
145 Clock* clock,
146 ReceiveStatistics* receive_statistics,
sprang86fd9ed2015-09-29 04:45:43 -0700147 RtcpPacketTypeCounterObserver* packet_type_counter_observer,
148 Transport* outgoing_transport)
Peter Boströmac547a62015-09-17 23:03:57 +0200149 : audio_(audio),
Erik Språng242e22b2015-05-11 10:17:43 +0200150 clock_(clock),
danilchap47a740b2015-12-15 00:30:07 -0800151 random_(clock_->TimeInMicroseconds()),
pbosda903ea2015-10-02 02:36:56 -0700152 method_(RtcpMode::kOff),
sprang86fd9ed2015-09-29 04:45:43 -0700153 transport_(outgoing_transport),
niklase@google.com470e71d2011-07-07 08:21:25 +0000154
Erik Språng242e22b2015-05-11 10:17:43 +0200155 critical_section_rtcp_sender_(
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000156 CriticalSectionWrapper::CreateCriticalSection()),
Erik Språng242e22b2015-05-11 10:17:43 +0200157 using_nack_(false),
158 sending_(false),
159 remb_enabled_(false),
Erik Språng242e22b2015-05-11 10:17:43 +0200160 next_time_to_send_rtcp_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000161 start_timestamp_(0),
162 last_rtp_timestamp_(0),
163 last_frame_capture_time_ms_(-1),
Erik Språng242e22b2015-05-11 10:17:43 +0200164 ssrc_(0),
165 remote_ssrc_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000166 receive_statistics_(receive_statistics),
niklase@google.com470e71d2011-07-07 08:21:25 +0000167
Erik Språng242e22b2015-05-11 10:17:43 +0200168 sequence_number_fir_(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000169
Erik Språng242e22b2015-05-11 10:17:43 +0200170 remb_bitrate_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000171
Erik Språng242e22b2015-05-11 10:17:43 +0200172 tmmbr_help_(),
173 tmmbr_send_(0),
174 packet_oh_send_(0),
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000175
Erik Språng242e22b2015-05-11 10:17:43 +0200176 app_sub_type_(0),
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200177 app_name_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200178 app_data_(nullptr),
179 app_length_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000180
Erik Språng242e22b2015-05-11 10:17:43 +0200181 xr_send_receiver_reference_time_enabled_(false),
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000182 packet_type_counter_observer_(packet_type_counter_observer) {
Erik Språng242e22b2015-05-11 10:17:43 +0200183 memset(last_send_report_, 0, sizeof(last_send_report_));
184 memset(last_rtcp_time_, 0, sizeof(last_rtcp_time_));
sprang86fd9ed2015-09-29 04:45:43 -0700185 RTC_DCHECK(transport_ != nullptr);
Erik Språng242e22b2015-05-11 10:17:43 +0200186
187 builders_[kRtcpSr] = &RTCPSender::BuildSR;
188 builders_[kRtcpRr] = &RTCPSender::BuildRR;
Erik Språng0ea42d32015-06-25 14:46:16 +0200189 builders_[kRtcpSdes] = &RTCPSender::BuildSDES;
Erik Språng242e22b2015-05-11 10:17:43 +0200190 builders_[kRtcpPli] = &RTCPSender::BuildPLI;
191 builders_[kRtcpFir] = &RTCPSender::BuildFIR;
192 builders_[kRtcpSli] = &RTCPSender::BuildSLI;
193 builders_[kRtcpRpsi] = &RTCPSender::BuildRPSI;
194 builders_[kRtcpRemb] = &RTCPSender::BuildREMB;
195 builders_[kRtcpBye] = &RTCPSender::BuildBYE;
196 builders_[kRtcpApp] = &RTCPSender::BuildAPP;
197 builders_[kRtcpTmmbr] = &RTCPSender::BuildTMMBR;
198 builders_[kRtcpTmmbn] = &RTCPSender::BuildTMMBN;
199 builders_[kRtcpNack] = &RTCPSender::BuildNACK;
200 builders_[kRtcpXrVoipMetric] = &RTCPSender::BuildVoIPMetric;
201 builders_[kRtcpXrReceiverReferenceTime] =
202 &RTCPSender::BuildReceiverReferenceTime;
203 builders_[kRtcpXrDlrrReportBlock] = &RTCPSender::BuildDlrr;
niklase@google.com470e71d2011-07-07 08:21:25 +0000204}
205
danilchap162abd32015-12-10 02:39:40 -0800206RTCPSender::~RTCPSender() {}
niklase@google.com470e71d2011-07-07 08:21:25 +0000207
pbosda903ea2015-10-02 02:36:56 -0700208RtcpMode RTCPSender::Status() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200209 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
210 return method_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000211}
212
pbosda903ea2015-10-02 02:36:56 -0700213void RTCPSender::SetRTCPStatus(RtcpMode method) {
Erik Språng242e22b2015-05-11 10:17:43 +0200214 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
215 method_ = method;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000216
pbosda903ea2015-10-02 02:36:56 -0700217 if (method == RtcpMode::kOff)
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000218 return;
Erik Språng242e22b2015-05-11 10:17:43 +0200219 next_time_to_send_rtcp_ =
220 clock_->TimeInMilliseconds() +
221 (audio_ ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000222}
223
Erik Språng61be2a42015-04-27 13:32:52 +0200224bool RTCPSender::Sending() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200225 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
226 return sending_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000227}
228
Erik Språng61be2a42015-04-27 13:32:52 +0200229int32_t RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
230 bool sending) {
231 bool sendRTCPBye = false;
232 {
Erik Språng242e22b2015-05-11 10:17:43 +0200233 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000234
pbosda903ea2015-10-02 02:36:56 -0700235 if (method_ != RtcpMode::kOff) {
Erik Språng242e22b2015-05-11 10:17:43 +0200236 if (sending == false && sending_ == true) {
Erik Språng61be2a42015-04-27 13:32:52 +0200237 // Trigger RTCP bye
238 sendRTCPBye = true;
239 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000240 }
Erik Språng242e22b2015-05-11 10:17:43 +0200241 sending_ = sending;
Erik Språng61be2a42015-04-27 13:32:52 +0200242 }
243 if (sendRTCPBye)
244 return SendRTCP(feedback_state, kRtcpBye);
245 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000246}
247
Erik Språng61be2a42015-04-27 13:32:52 +0200248bool RTCPSender::REMB() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200249 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
250 return remb_enabled_;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000251}
252
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000253void RTCPSender::SetREMBStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200254 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
255 remb_enabled_ = enable;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000256}
257
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000258void RTCPSender::SetREMBData(uint32_t bitrate,
259 const std::vector<uint32_t>& ssrcs) {
Erik Språng242e22b2015-05-11 10:17:43 +0200260 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
261 remb_bitrate_ = bitrate;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000262 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000263
Erik Språng242e22b2015-05-11 10:17:43 +0200264 if (remb_enabled_)
265 SetFlag(kRtcpRemb, false);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000266 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
267 // throttled by the caller.
Erik Språng242e22b2015-05-11 10:17:43 +0200268 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000269}
270
Erik Språng61be2a42015-04-27 13:32:52 +0200271bool RTCPSender::TMMBR() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200272 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
273 return IsFlagPresent(RTCPPacketType::kRtcpTmmbr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000274}
275
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000276void RTCPSender::SetTMMBRStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200277 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
278 if (enable) {
279 SetFlag(RTCPPacketType::kRtcpTmmbr, false);
280 } else {
281 ConsumeFlag(RTCPPacketType::kRtcpTmmbr, true);
282 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000283}
284
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000285void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
Erik Språng242e22b2015-05-11 10:17:43 +0200286 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000287 start_timestamp_ = start_timestamp;
288}
289
290void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
291 int64_t capture_time_ms) {
Erik Språng242e22b2015-05-11 10:17:43 +0200292 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000293 last_rtp_timestamp_ = rtp_timestamp;
294 if (capture_time_ms < 0) {
295 // We don't currently get a capture time from VoiceEngine.
Erik Språng242e22b2015-05-11 10:17:43 +0200296 last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000297 } else {
298 last_frame_capture_time_ms_ = capture_time_ms;
299 }
300}
301
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000302void RTCPSender::SetSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200303 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000304
Erik Språng242e22b2015-05-11 10:17:43 +0200305 if (ssrc_ != 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200306 // not first SetSSRC, probably due to a collision
307 // schedule a new RTCP report
308 // make sure that we send a RTP packet
Erik Språng242e22b2015-05-11 10:17:43 +0200309 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
Erik Språng61be2a42015-04-27 13:32:52 +0200310 }
Erik Språng242e22b2015-05-11 10:17:43 +0200311 ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000312}
313
Erik Språng61be2a42015-04-27 13:32:52 +0200314void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200315 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
316 remote_ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000317}
318
Peter Boström9ba52f82015-06-01 14:12:28 +0200319int32_t RTCPSender::SetCNAME(const char* c_name) {
320 if (!c_name)
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000321 return -1;
322
henrikg91d6ede2015-09-17 00:24:34 -0700323 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
Erik Språng242e22b2015-05-11 10:17:43 +0200324 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200325 cname_ = c_name;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000326 return 0;
327}
328
Erik Språng0ea42d32015-06-25 14:46:16 +0200329int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC, const char* c_name) {
330 assert(c_name);
henrikg91d6ede2015-09-17 00:24:34 -0700331 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
Erik Språng242e22b2015-05-11 10:17:43 +0200332 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200333 if (csrc_cnames_.size() >= kRtpCsrcSize)
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000334 return -1;
Erik Språng0ea42d32015-06-25 14:46:16 +0200335
336 csrc_cnames_[SSRC] = c_name;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000337 return 0;
338}
339
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000340int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
Erik Språng242e22b2015-05-11 10:17:43 +0200341 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200342 auto it = csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000343
Erik Språng242e22b2015-05-11 10:17:43 +0200344 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000345 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200346
Erik Språng242e22b2015-05-11 10:17:43 +0200347 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000348 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000349}
350
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000351bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
danilchap162abd32015-12-10 02:39:40 -0800352 /*
353 For audio we use a fix 5 sec interval
niklase@google.com470e71d2011-07-07 08:21:25 +0000354
danilchap162abd32015-12-10 02:39:40 -0800355 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
356 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
357 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000358
359
danilchap162abd32015-12-10 02:39:40 -0800360 From RFC 3550
niklase@google.com470e71d2011-07-07 08:21:25 +0000361
danilchap162abd32015-12-10 02:39:40 -0800362 MAX RTCP BW is 5% if the session BW
363 A send report is approximately 65 bytes inc CNAME
364 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000365
danilchap162abd32015-12-10 02:39:40 -0800366 The RECOMMENDED value for the reduced minimum in seconds is 360
367 divided by the session bandwidth in kilobits/second. This minimum
368 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
niklase@google.com470e71d2011-07-07 08:21:25 +0000369
danilchap162abd32015-12-10 02:39:40 -0800370 If the participant has not yet sent an RTCP packet (the variable
371 initial is true), the constant Tmin is set to 2.5 seconds, else it
372 is set to 5 seconds.
niklase@google.com470e71d2011-07-07 08:21:25 +0000373
danilchap162abd32015-12-10 02:39:40 -0800374 The interval between RTCP packets is varied randomly over the
375 range [0.5,1.5] times the calculated interval to avoid unintended
376 synchronization of all participants
niklase@google.com470e71d2011-07-07 08:21:25 +0000377
danilchap162abd32015-12-10 02:39:40 -0800378 if we send
379 If the participant is a sender (we_sent true), the constant C is
380 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
381 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
382 number of senders.
niklase@google.com470e71d2011-07-07 08:21:25 +0000383
danilchap162abd32015-12-10 02:39:40 -0800384 if we receive only
385 If we_sent is not true, the constant C is set
386 to the average RTCP packet size divided by 75% of the RTCP
387 bandwidth. The constant n is set to the number of receivers
388 (members - senders). If the number of senders is greater than
389 25%, senders and receivers are treated together.
niklase@google.com470e71d2011-07-07 08:21:25 +0000390
danilchap162abd32015-12-10 02:39:40 -0800391 reconsideration NOT required for peer-to-peer
392 "timer reconsideration" is
393 employed. This algorithm implements a simple back-off mechanism
394 which causes users to hold back RTCP packet transmission if the
395 group sizes are increasing.
niklase@google.com470e71d2011-07-07 08:21:25 +0000396
danilchap162abd32015-12-10 02:39:40 -0800397 n = number of members
398 C = avg_size/(rtcpBW/4)
niklase@google.com470e71d2011-07-07 08:21:25 +0000399
danilchap162abd32015-12-10 02:39:40 -0800400 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
niklase@google.com470e71d2011-07-07 08:21:25 +0000401
danilchap162abd32015-12-10 02:39:40 -0800402 4. The calculated interval T is set to a number uniformly distributed
403 between 0.5 and 1.5 times the deterministic calculated interval.
niklase@google.com470e71d2011-07-07 08:21:25 +0000404
danilchap162abd32015-12-10 02:39:40 -0800405 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
406 for the fact that the timer reconsideration algorithm converges to
407 a value of the RTCP bandwidth below the intended average
408 */
niklase@google.com470e71d2011-07-07 08:21:25 +0000409
Erik Språng242e22b2015-05-11 10:17:43 +0200410 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000411
Erik Språng242e22b2015-05-11 10:17:43 +0200412 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
xians@webrtc.org8738d272011-11-25 13:43:53 +0000413
pbosda903ea2015-10-02 02:36:56 -0700414 if (method_ == RtcpMode::kOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000415 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000416
Erik Språng242e22b2015-05-11 10:17:43 +0200417 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200418 // for video key-frames we want to send the RTCP before the large key-frame
419 // if we have a 100 ms margin
420 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
421 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000422
Erik Språng242e22b2015-05-11 10:17:43 +0200423 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200424 return true;
425 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200426 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200427 // wrap
428 return true;
429 }
430 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000431}
432
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000433int64_t RTCPSender::SendTimeOfSendReport(uint32_t sendReport) {
Erik Språng242e22b2015-05-11 10:17:43 +0200434 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000435
Erik Språng61be2a42015-04-27 13:32:52 +0200436 // This is only saved when we are the sender
Erik Språng242e22b2015-05-11 10:17:43 +0200437 if ((last_send_report_[0] == 0) || (sendReport == 0)) {
Erik Språng61be2a42015-04-27 13:32:52 +0200438 return 0; // will be ignored
439 } else {
440 for (int i = 0; i < RTCP_NUMBER_OF_SR; ++i) {
Erik Språng242e22b2015-05-11 10:17:43 +0200441 if (last_send_report_[i] == sendReport)
442 return last_rtcp_time_[i];
niklase@google.com470e71d2011-07-07 08:21:25 +0000443 }
Erik Språng61be2a42015-04-27 13:32:52 +0200444 }
445 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000446}
447
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000448bool RTCPSender::SendTimeOfXrRrReport(uint32_t mid_ntp,
449 int64_t* time_ms) const {
Erik Språng242e22b2015-05-11 10:17:43 +0200450 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000451
452 if (last_xr_rr_.empty()) {
453 return false;
454 }
455 std::map<uint32_t, int64_t>::const_iterator it = last_xr_rr_.find(mid_ntp);
456 if (it == last_xr_rr_.end()) {
457 return false;
458 }
459 *time_ms = it->second;
460 return true;
461}
462
Erik Språngf7c57762015-12-04 10:40:35 +0100463rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildSR(const RtcpContext& ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200464 for (int i = (RTCP_NUMBER_OF_SR - 2); i >= 0; i--) {
465 // shift old
Erik Språng242e22b2015-05-11 10:17:43 +0200466 last_send_report_[i + 1] = last_send_report_[i];
467 last_rtcp_time_[i + 1] = last_rtcp_time_[i];
Erik Språng61be2a42015-04-27 13:32:52 +0200468 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000469
Erik Språngf7c57762015-12-04 10:40:35 +0100470 last_rtcp_time_[0] = Clock::NtpToMs(ctx.ntp_sec_, ctx.ntp_frac_);
471 last_send_report_[0] = (ctx.ntp_sec_ << 16) + (ctx.ntp_frac_ >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000472
Erik Språng61be2a42015-04-27 13:32:52 +0200473 // The timestamp of this RTCP packet should be estimated as the timestamp of
474 // the frame being captured at this moment. We are calculating that
475 // timestamp as the last frame's timestamp + the time since the last frame
476 // was captured.
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200477 uint32_t rtp_timestamp =
478 start_timestamp_ + last_rtp_timestamp_ +
479 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) *
Erik Språngf7c57762015-12-04 10:40:35 +0100480 (ctx.feedback_state_.frequency_hz / 1000);
niklase@google.com470e71d2011-07-07 08:21:25 +0000481
Erik Språngf7c57762015-12-04 10:40:35 +0100482 rtcp::SenderReport* report = new rtcp::SenderReport();
483 report->From(ssrc_);
484 report->WithNtpSec(ctx.ntp_sec_);
485 report->WithNtpFrac(ctx.ntp_frac_);
486 report->WithRtpTimestamp(rtp_timestamp);
487 report->WithPacketCount(ctx.feedback_state_.packets_sent);
488 report->WithOctetCount(ctx.feedback_state_.media_bytes_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000489
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200490 for (auto it : report_blocks_)
Erik Språngf7c57762015-12-04 10:40:35 +0100491 report->WithReportBlock(it.second);
niklase@google.com470e71d2011-07-07 08:21:25 +0000492
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200493 report_blocks_.clear();
Erik Språngf7c57762015-12-04 10:40:35 +0100494
495 return rtc::scoped_ptr<rtcp::SenderReport>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000496}
497
Erik Språngf7c57762015-12-04 10:40:35 +0100498rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildSDES(
499 const RtcpContext& ctx) {
Erik Språng0ea42d32015-06-25 14:46:16 +0200500 size_t length_cname = cname_.length();
henrikg91d6ede2015-09-17 00:24:34 -0700501 RTC_CHECK_LT(length_cname, static_cast<size_t>(RTCP_CNAME_SIZE));
niklase@google.com470e71d2011-07-07 08:21:25 +0000502
Erik Språngf7c57762015-12-04 10:40:35 +0100503 rtcp::Sdes* sdes = new rtcp::Sdes();
504 sdes->WithCName(ssrc_, cname_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200505
506 for (const auto it : csrc_cnames_)
Erik Språngf7c57762015-12-04 10:40:35 +0100507 sdes->WithCName(it.first, it.second);
Erik Språng0ea42d32015-06-25 14:46:16 +0200508
Erik Språngf7c57762015-12-04 10:40:35 +0100509 return rtc::scoped_ptr<rtcp::Sdes>(sdes);
niklase@google.com470e71d2011-07-07 08:21:25 +0000510}
511
Erik Språngf7c57762015-12-04 10:40:35 +0100512rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildRR(const RtcpContext& ctx) {
513 rtcp::ReceiverReport* report = new rtcp::ReceiverReport();
514 report->From(ssrc_);
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200515 for (auto it : report_blocks_)
Erik Språngf7c57762015-12-04 10:40:35 +0100516 report->WithReportBlock(it.second);
Erik Språng61be2a42015-04-27 13:32:52 +0200517
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200518 report_blocks_.clear();
Erik Språngf7c57762015-12-04 10:40:35 +0100519 return rtc::scoped_ptr<rtcp::ReceiverReport>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000520}
521
Erik Språngf7c57762015-12-04 10:40:35 +0100522rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildPLI(const RtcpContext& ctx) {
523 rtcp::Pli* pli = new rtcp::Pli();
524 pli->From(ssrc_);
525 pli->To(remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200526
Erik Språng242e22b2015-05-11 10:17:43 +0200527 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
528 "RTCPSender::PLI");
529 ++packet_type_counter_.pli_packets;
530 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
531 ssrc_, packet_type_counter_.pli_packets);
532
Erik Språngf7c57762015-12-04 10:40:35 +0100533 return rtc::scoped_ptr<rtcp::Pli>(pli);
Erik Språng61be2a42015-04-27 13:32:52 +0200534}
535
Erik Språngf7c57762015-12-04 10:40:35 +0100536rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildFIR(const RtcpContext& ctx) {
537 if (!ctx.repeat_)
sprang62dae192015-08-05 02:35:35 -0700538 ++sequence_number_fir_; // Do not increase if repetition.
niklase@google.com470e71d2011-07-07 08:21:25 +0000539
Erik Språngf7c57762015-12-04 10:40:35 +0100540 rtcp::Fir* fir = new rtcp::Fir();
541 fir->From(ssrc_);
542 fir->To(remote_ssrc_);
543 fir->WithCommandSeqNum(sequence_number_fir_);
Erik Språng242e22b2015-05-11 10:17:43 +0200544
545 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
546 "RTCPSender::FIR");
547 ++packet_type_counter_.fir_packets;
548 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
549 ssrc_, packet_type_counter_.fir_packets);
550
Erik Språngf7c57762015-12-04 10:40:35 +0100551 return rtc::scoped_ptr<rtcp::Fir>(fir);
niklase@google.com470e71d2011-07-07 08:21:25 +0000552}
553
554/*
555 0 1 2 3
556 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
557 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
558 | First | Number | PictureID |
559 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
560*/
Erik Språngf7c57762015-12-04 10:40:35 +0100561rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildSLI(const RtcpContext& ctx) {
562 rtcp::Sli* sli = new rtcp::Sli();
563 sli->From(ssrc_);
564 sli->To(remote_ssrc_);
sprang0365a272015-08-11 01:02:37 -0700565 // Crop picture id to 6 least significant bits.
Erik Språngf7c57762015-12-04 10:40:35 +0100566 sli->WithPictureId(ctx.picture_id_ & 0x3F);
sprang0365a272015-08-11 01:02:37 -0700567
Erik Språngf7c57762015-12-04 10:40:35 +0100568 return rtc::scoped_ptr<rtcp::Sli>(sli);
niklase@google.com470e71d2011-07-07 08:21:25 +0000569}
570
571/*
572 0 1 2 3
573 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
574 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
575 | PB |0| Payload Type| Native RPSI bit string |
576 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
577 | defined per codec ... | Padding (0) |
578 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
579*/
580/*
581* Note: not generic made for VP8
582*/
Erik Språngf7c57762015-12-04 10:40:35 +0100583rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildRPSI(
584 const RtcpContext& ctx) {
585 if (ctx.feedback_state_.send_payload_type == 0xFF)
586 return nullptr;
Erik Språng242e22b2015-05-11 10:17:43 +0200587
Erik Språngf7c57762015-12-04 10:40:35 +0100588 rtcp::Rpsi* rpsi = new rtcp::Rpsi();
589 rpsi->From(ssrc_);
590 rpsi->To(remote_ssrc_);
591 rpsi->WithPayloadType(ctx.feedback_state_.send_payload_type);
592 rpsi->WithPictureId(ctx.picture_id_);
sprangcf7f54d2015-08-13 04:37:42 -0700593
Erik Språngf7c57762015-12-04 10:40:35 +0100594 return rtc::scoped_ptr<rtcp::Rpsi>(rpsi);
niklase@google.com470e71d2011-07-07 08:21:25 +0000595}
596
Erik Språngf7c57762015-12-04 10:40:35 +0100597rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildREMB(
598 const RtcpContext& ctx) {
599 rtcp::Remb* remb = new rtcp::Remb();
600 remb->From(ssrc_);
sprangdd4edc52015-08-21 04:21:51 -0700601 for (uint32_t ssrc : remb_ssrcs_)
Erik Språngf7c57762015-12-04 10:40:35 +0100602 remb->AppliesTo(ssrc);
603 remb->WithBitrateBps(remb_bitrate_);
Erik Språng61be2a42015-04-27 13:32:52 +0200604
Erik Språng242e22b2015-05-11 10:17:43 +0200605 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
606 "RTCPSender::REMB");
607
Erik Språngf7c57762015-12-04 10:40:35 +0100608 return rtc::scoped_ptr<rtcp::Remb>(remb);
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000609}
610
Erik Språng61be2a42015-04-27 13:32:52 +0200611void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
Erik Språng242e22b2015-05-11 10:17:43 +0200612 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
613 tmmbr_send_ = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000614}
615
Erik Språngf7c57762015-12-04 10:40:35 +0100616rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBR(
617 const RtcpContext& ctx) {
618 if (ctx.feedback_state_.module == nullptr)
619 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200620 // Before sending the TMMBR check the received TMMBN, only an owner is
621 // allowed to raise the bitrate:
622 // * If the sender is an owner of the TMMBN -> send TMMBR
623 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000624
Erik Språng61be2a42015-04-27 13:32:52 +0200625 // get current bounding set from RTCP receiver
626 bool tmmbrOwner = false;
627 // store in candidateSet, allocates one extra slot
Erik Språng242e22b2015-05-11 10:17:43 +0200628 TMMBRSet* candidateSet = tmmbr_help_.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000629
Erik Språng242e22b2015-05-11 10:17:43 +0200630 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
631 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
Erik Språng61be2a42015-04-27 13:32:52 +0200632 // since RTCPreceiver is not doing the reverse we should be fine
633 int32_t lengthOfBoundingSet =
danilchap6db6cdc2015-12-15 02:54:47 -0800634 ctx.feedback_state_.module->BoundingSet(&tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +0000635
Erik Språng61be2a42015-04-27 13:32:52 +0200636 if (lengthOfBoundingSet > 0) {
637 for (int32_t i = 0; i < lengthOfBoundingSet; i++) {
Erik Språng242e22b2015-05-11 10:17:43 +0200638 if (candidateSet->Tmmbr(i) == tmmbr_send_ &&
639 candidateSet->PacketOH(i) == packet_oh_send_) {
Erik Språngf7c57762015-12-04 10:40:35 +0100640 // Do not send the same tuple.
641 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200642 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000643 }
Erik Språng61be2a42015-04-27 13:32:52 +0200644 if (!tmmbrOwner) {
645 // use received bounding set as candidate set
646 // add current tuple
Erik Språng242e22b2015-05-11 10:17:43 +0200647 candidateSet->SetEntry(lengthOfBoundingSet, tmmbr_send_, packet_oh_send_,
648 ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200649 int numCandidates = lengthOfBoundingSet + 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000650
Erik Språng61be2a42015-04-27 13:32:52 +0200651 // find bounding set
Erik Språngf7c57762015-12-04 10:40:35 +0100652 TMMBRSet* boundingSet = nullptr;
Erik Språng242e22b2015-05-11 10:17:43 +0200653 int numBoundingSet = tmmbr_help_.FindTMMBRBoundingSet(boundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200654 if (numBoundingSet > 0 || numBoundingSet <= numCandidates)
Erik Språng242e22b2015-05-11 10:17:43 +0200655 tmmbrOwner = tmmbr_help_.IsOwner(ssrc_, numBoundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200656 if (!tmmbrOwner) {
Erik Språngf7c57762015-12-04 10:40:35 +0100657 // Did not enter bounding set, no meaning to send this request.
658 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200659 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000660 }
Erik Språng61be2a42015-04-27 13:32:52 +0200661 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000662
Erik Språngf7c57762015-12-04 10:40:35 +0100663 if (!tmmbr_send_)
664 return nullptr;
sprang81a3e602015-08-21 05:30:11 -0700665
Erik Språngf7c57762015-12-04 10:40:35 +0100666 rtcp::Tmmbr* tmmbr = new rtcp::Tmmbr();
667 tmmbr->From(ssrc_);
668 tmmbr->To(remote_ssrc_);
669 tmmbr->WithBitrateKbps(tmmbr_send_);
670 tmmbr->WithOverhead(packet_oh_send_);
671
672 return rtc::scoped_ptr<rtcp::Tmmbr>(tmmbr);
Erik Språng61be2a42015-04-27 13:32:52 +0200673}
674
Erik Språngf7c57762015-12-04 10:40:35 +0100675rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBN(
676 const RtcpContext& ctx) {
Erik Språng242e22b2015-05-11 10:17:43 +0200677 TMMBRSet* boundingSet = tmmbr_help_.BoundingSetToSend();
Erik Språngf7c57762015-12-04 10:40:35 +0100678 if (boundingSet == nullptr)
679 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200680
Erik Språngf7c57762015-12-04 10:40:35 +0100681 rtcp::Tmmbn* tmmbn = new rtcp::Tmmbn();
682 tmmbn->From(ssrc_);
sprangd83df502015-08-27 01:05:08 -0700683 for (uint32_t i = 0; i < boundingSet->lengthOfSet(); i++) {
684 if (boundingSet->Tmmbr(i) > 0) {
Erik Språngf7c57762015-12-04 10:40:35 +0100685 tmmbn->WithTmmbr(boundingSet->Ssrc(i), boundingSet->Tmmbr(i),
686 boundingSet->PacketOH(i));
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000687 }
Erik Språng61be2a42015-04-27 13:32:52 +0200688 }
sprangd83df502015-08-27 01:05:08 -0700689
Erik Språngf7c57762015-12-04 10:40:35 +0100690 return rtc::scoped_ptr<rtcp::Tmmbn>(tmmbn);
niklase@google.com470e71d2011-07-07 08:21:25 +0000691}
692
Erik Språngf7c57762015-12-04 10:40:35 +0100693rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildAPP(const RtcpContext& ctx) {
694 rtcp::App* app = new rtcp::App();
695 app->From(ssrc_);
696 app->WithSubType(app_sub_type_);
697 app->WithName(app_name_);
698 app->WithData(app_data_.get(), app_length_);
Erik Språng521875a2015-09-01 10:11:16 +0200699
Erik Språngf7c57762015-12-04 10:40:35 +0100700 return rtc::scoped_ptr<rtcp::App>(app);
Erik Språng61be2a42015-04-27 13:32:52 +0200701}
702
Erik Språngf7c57762015-12-04 10:40:35 +0100703rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildNACK(
704 const RtcpContext& ctx) {
705 rtcp::Nack* nack = new rtcp::Nack();
706 nack->From(ssrc_);
707 nack->To(remote_ssrc_);
708 nack->WithList(ctx.nack_list_, ctx.nack_size_);
Erik Språng61be2a42015-04-27 13:32:52 +0200709
710 // Report stats.
711 NACKStringBuilder stringBuilder;
Erik Språngf7c57762015-12-04 10:40:35 +0100712 for (int idx = 0; idx < ctx.nack_size_; ++idx) {
713 stringBuilder.PushNACK(ctx.nack_list_[idx]);
714 nack_stats_.ReportRequest(ctx.nack_list_[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +0200715 }
Erik Språng61be2a42015-04-27 13:32:52 +0200716 packet_type_counter_.nack_requests = nack_stats_.requests();
717 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +0200718
719 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
720 "RTCPSender::NACK", "nacks",
721 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
722 ++packet_type_counter_.nack_packets;
723 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
724 ssrc_, packet_type_counter_.nack_packets);
725
Erik Språngf7c57762015-12-04 10:40:35 +0100726 return rtc::scoped_ptr<rtcp::Nack>(nack);
Erik Språng61be2a42015-04-27 13:32:52 +0200727}
728
Erik Språngf7c57762015-12-04 10:40:35 +0100729rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildBYE(const RtcpContext& ctx) {
730 rtcp::Bye* bye = new rtcp::Bye();
731 bye->From(ssrc_);
sprangd8ee4f92015-08-24 03:25:19 -0700732 for (uint32_t csrc : csrcs_)
Erik Språngf7c57762015-12-04 10:40:35 +0100733 bye->WithCsrc(csrc);
sprangd8ee4f92015-08-24 03:25:19 -0700734
Erik Språngf7c57762015-12-04 10:40:35 +0100735 return rtc::scoped_ptr<rtcp::Bye>(bye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000736}
737
Erik Språngf7c57762015-12-04 10:40:35 +0100738rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildReceiverReferenceTime(
739 const RtcpContext& ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200740 if (last_xr_rr_.size() >= RTCP_NUMBER_OF_SR)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000741 last_xr_rr_.erase(last_xr_rr_.begin());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000742 last_xr_rr_.insert(std::pair<uint32_t, int64_t>(
Erik Språngf7c57762015-12-04 10:40:35 +0100743 RTCPUtility::MidNtp(ctx.ntp_sec_, ctx.ntp_frac_),
744 Clock::NtpToMs(ctx.ntp_sec_, ctx.ntp_frac_)));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000745
Danil Chapovalov256e5b22016-01-15 14:16:24 +0100746 rtcp::ExtendedReports* xr = new rtcp::ExtendedReports();
Erik Språngf7c57762015-12-04 10:40:35 +0100747 xr->From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000748
Erik Språngca28fdc2015-08-31 14:00:50 +0200749 rtcp::Rrtr rrtr;
Danil Chapovalovfc47ed62015-12-07 14:46:35 +0100750 rrtr.WithNtp(NtpTime(ctx.ntp_sec_, ctx.ntp_frac_));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000751
Erik Språngf7c57762015-12-04 10:40:35 +0100752 xr->WithRrtr(&rrtr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000753
Erik Språngca28fdc2015-08-31 14:00:50 +0200754 // TODO(sprang): Merge XR report sending to contain all of RRTR, DLRR, VOIP?
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000755
Danil Chapovalov256e5b22016-01-15 14:16:24 +0100756 return rtc::scoped_ptr<rtcp::RtcpPacket>(xr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000757}
758
Erik Språngf7c57762015-12-04 10:40:35 +0100759rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildDlrr(
760 const RtcpContext& ctx) {
Danil Chapovalov256e5b22016-01-15 14:16:24 +0100761 rtcp::ExtendedReports* xr = new rtcp::ExtendedReports();
Erik Språngf7c57762015-12-04 10:40:35 +0100762 xr->From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000763
Erik Språngca28fdc2015-08-31 14:00:50 +0200764 rtcp::Dlrr dlrr;
Erik Språngf7c57762015-12-04 10:40:35 +0100765 const RtcpReceiveTimeInfo& info = ctx.feedback_state_.last_xr_rr;
Erik Språngca28fdc2015-08-31 14:00:50 +0200766 dlrr.WithDlrrItem(info.sourceSSRC, info.lastRR, info.delaySinceLastRR);
767
Erik Språngf7c57762015-12-04 10:40:35 +0100768 xr->WithDlrr(&dlrr);
Erik Språngca28fdc2015-08-31 14:00:50 +0200769
Danil Chapovalov256e5b22016-01-15 14:16:24 +0100770 return rtc::scoped_ptr<rtcp::RtcpPacket>(xr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000771}
772
Erik Språng242e22b2015-05-11 10:17:43 +0200773// TODO(sprang): Add a unit test for this, or remove if the code isn't used.
Erik Språngf7c57762015-12-04 10:40:35 +0100774rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildVoIPMetric(
775 const RtcpContext& context) {
Danil Chapovalov256e5b22016-01-15 14:16:24 +0100776 rtcp::ExtendedReports* xr = new rtcp::ExtendedReports();
Erik Språngf7c57762015-12-04 10:40:35 +0100777 xr->From(ssrc_);
Erik Språngca28fdc2015-08-31 14:00:50 +0200778
779 rtcp::VoipMetric voip;
780 voip.To(remote_ssrc_);
danilchap91941ae2015-12-15 07:06:36 -0800781 voip.WithVoipMetric(xr_voip_metric_);
Erik Språngca28fdc2015-08-31 14:00:50 +0200782
Erik Språngf7c57762015-12-04 10:40:35 +0100783 xr->WithVoipMetric(&voip);
Erik Språngca28fdc2015-08-31 14:00:50 +0200784
Danil Chapovalov256e5b22016-01-15 14:16:24 +0100785 return rtc::scoped_ptr<rtcp::RtcpPacket>(xr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000786}
787
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000788int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200789 RTCPPacketType packetType,
790 int32_t nack_size,
791 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000792 bool repeat,
793 uint64_t pictureID) {
Erik Språng242e22b2015-05-11 10:17:43 +0200794 return SendCompoundRTCP(
795 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
796 nack_size, nack_list, repeat, pictureID);
797}
798
799int32_t RTCPSender::SendCompoundRTCP(
800 const FeedbackState& feedback_state,
Erik Språngf7c57762015-12-04 10:40:35 +0100801 const std::set<RTCPPacketType>& packet_types,
Erik Språng242e22b2015-05-11 10:17:43 +0200802 int32_t nack_size,
803 const uint16_t* nack_list,
804 bool repeat,
805 uint64_t pictureID) {
Erik Språngf7c57762015-12-04 10:40:35 +0100806 PacketContainer container(transport_);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000807 {
Erik Språng242e22b2015-05-11 10:17:43 +0200808 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
pbosda903ea2015-10-02 02:36:56 -0700809 if (method_ == RtcpMode::kOff) {
Erik Språng61be2a42015-04-27 13:32:52 +0200810 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
811 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +0000812 }
Erik Språngf7c57762015-12-04 10:40:35 +0100813
814 // We need to send our NTP even if we haven't received any reports.
815 uint32_t ntp_sec;
816 uint32_t ntp_frac;
817 clock_->CurrentNtp(ntp_sec, ntp_frac);
818 RtcpContext context(feedback_state, nack_size, nack_list, repeat, pictureID,
819 ntp_sec, ntp_frac, &container);
820
821 PrepareReport(packet_types, feedback_state);
822
823 auto it = report_flags_.begin();
824 while (it != report_flags_.end()) {
825 auto builder_it = builders_.find(it->type);
826 RTC_DCHECK(builder_it != builders_.end());
827 if (it->is_volatile) {
828 report_flags_.erase(it++);
829 } else {
830 ++it;
831 }
832
833 BuilderFunc func = builder_it->second;
834 rtc::scoped_ptr<rtcp::RtcpPacket> packet = (this->*func)(context);
835 if (packet.get() == nullptr)
836 return -1;
837 container.Append(packet.release());
838 }
839
840 if (packet_type_counter_observer_ != nullptr) {
841 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
842 remote_ssrc_, packet_type_counter_);
843 }
844
845 RTC_DCHECK(AllVolatileFlagsConsumed());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000846 }
Erik Språng61be2a42015-04-27 13:32:52 +0200847
Erik Språngf7c57762015-12-04 10:40:35 +0100848 size_t bytes_sent = container.SendPackets();
849 return bytes_sent == 0 ? -1 : 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000850}
851
Erik Språngf7c57762015-12-04 10:40:35 +0100852void RTCPSender::PrepareReport(const std::set<RTCPPacketType>& packetTypes,
853 const FeedbackState& feedback_state) {
Erik Språng242e22b2015-05-11 10:17:43 +0200854 // Add all flags as volatile. Non volatile entries will not be overwritten
855 // and all new volatile flags added will be consumed by the end of this call.
856 SetFlags(packetTypes, true);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000857
Erik Språng61be2a42015-04-27 13:32:52 +0200858 if (packet_type_counter_.first_packet_time_ms == -1)
Erik Språng242e22b2015-05-11 10:17:43 +0200859 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språng61be2a42015-04-27 13:32:52 +0200860
Erik Språng242e22b2015-05-11 10:17:43 +0200861 bool generate_report;
862 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
863 // Report type already explicitly set, don't automatically populate.
864 generate_report = true;
henrikg91d6ede2015-09-17 00:24:34 -0700865 RTC_DCHECK(ConsumeFlag(kRtcpReport) == false);
Erik Språng242e22b2015-05-11 10:17:43 +0200866 } else {
867 generate_report =
pbosda903ea2015-10-02 02:36:56 -0700868 (ConsumeFlag(kRtcpReport) && method_ == RtcpMode::kReducedSize) ||
869 method_ == RtcpMode::kCompound;
Erik Språng242e22b2015-05-11 10:17:43 +0200870 if (generate_report)
871 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000872 }
873
Erik Språng0ea42d32015-06-25 14:46:16 +0200874 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
Erik Språng242e22b2015-05-11 10:17:43 +0200875 SetFlag(kRtcpSdes, true);
876
Erik Språng242e22b2015-05-11 10:17:43 +0200877 if (generate_report) {
878 if (!sending_ && xr_send_receiver_reference_time_enabled_)
879 SetFlag(kRtcpXrReceiverReferenceTime, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200880 if (feedback_state.has_last_xr_rr)
Erik Språng242e22b2015-05-11 10:17:43 +0200881 SetFlag(kRtcpXrDlrrReportBlock, true);
882
883 // generate next time to send an RTCP report
danilchap47a740b2015-12-15 00:30:07 -0800884 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000885
danilchap47a740b2015-12-15 00:30:07 -0800886 if (!audio_) {
Erik Språng242e22b2015-05-11 10:17:43 +0200887 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200888 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
889 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
890 if (send_bitrate_kbit != 0)
891 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000892 }
Erik Språng61be2a42015-04-27 13:32:52 +0200893 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
894 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
Erik Språng61be2a42015-04-27 13:32:52 +0200895 }
danilchap47a740b2015-12-15 00:30:07 -0800896 // The interval between RTCP packets is varied randomly over the
897 // range [1/2,3/2] times the calculated interval.
898 uint32_t timeToNext =
899 random_.Rand(minIntervalMs * 1 / 2, minIntervalMs * 3 / 2);
Erik Språng242e22b2015-05-11 10:17:43 +0200900 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000901
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000902 StatisticianMap statisticians =
903 receive_statistics_->GetActiveStatisticians();
danilchapa72e7342015-12-22 08:07:45 -0800904 RTC_DCHECK(report_blocks_.empty());
905 for (auto& it : statisticians) {
906 AddReportBlock(feedback_state, it.first, it.second);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000907 }
908 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000909}
910
danilchapa72e7342015-12-22 08:07:45 -0800911bool RTCPSender::AddReportBlock(const FeedbackState& feedback_state,
912 uint32_t ssrc,
913 StreamStatistician* statistician) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000914 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000915 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000916 if (!statistician->GetStatistics(&stats, true))
917 return false;
danilchapa72e7342015-12-22 08:07:45 -0800918
919 if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) {
920 LOG(LS_WARNING) << "Too many report blocks.";
921 return false;
922 }
923 RTC_DCHECK(report_blocks_.find(ssrc) == report_blocks_.end());
924 rtcp::ReportBlock* block = &report_blocks_[ssrc];
925 block->To(ssrc);
926 block->WithFractionLost(stats.fraction_lost);
927 if (!block->WithCumulativeLost(stats.cumulative_lost)) {
928 report_blocks_.erase(ssrc);
929 LOG(LS_WARNING) << "Cumulative lost is oversized.";
930 return false;
931 }
932 block->WithExtHighestSeqNum(stats.extended_max_sequence_number);
933 block->WithJitter(stats.jitter);
934 block->WithLastSr(feedback_state.remote_sr);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000935
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200936 // TODO(sprang): Do we really need separate time stamps for each report?
937 // Get our NTP as late as possible to avoid a race.
938 uint32_t ntp_secs;
939 uint32_t ntp_frac;
940 clock_->CurrentNtp(ntp_secs, ntp_frac);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000941
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200942 // Delay since last received report.
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000943 if ((feedback_state.last_rr_ntp_secs != 0) ||
944 (feedback_state.last_rr_ntp_frac != 0)) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200945 // Get the 16 lowest bits of seconds and the 16 highest bits of fractions.
946 uint32_t now = ntp_secs & 0x0000FFFF;
Erik Språng61be2a42015-04-27 13:32:52 +0200947 now <<= 16;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200948 now += (ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000949
Erik Språng61be2a42015-04-27 13:32:52 +0200950 uint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
951 receiveTime <<= 16;
952 receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000953
danilchapa72e7342015-12-22 08:07:45 -0800954 block->WithDelayLastSr(now - receiveTime);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000955 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000956 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000957}
958
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000959void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
960 assert(csrcs.size() <= kRtpCsrcSize);
Erik Språng242e22b2015-05-11 10:17:43 +0200961 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000962 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +0000963}
964
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000965int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
966 uint32_t name,
967 const uint8_t* data,
968 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +0200969 if (length % 4 != 0) {
970 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
971 return -1;
972 }
Erik Språng242e22b2015-05-11 10:17:43 +0200973 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000974
Erik Språng242e22b2015-05-11 10:17:43 +0200975 SetFlag(kRtcpApp, true);
976 app_sub_type_ = subType;
977 app_name_ = name;
978 app_data_.reset(new uint8_t[length]);
979 app_length_ = length;
980 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +0200981 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000982}
983
Erik Språng61be2a42015-04-27 13:32:52 +0200984int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
Erik Språng242e22b2015-05-11 10:17:43 +0200985 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
986 memcpy(&xr_voip_metric_, VoIPMetric, sizeof(RTCPVoIPMetric));
niklase@google.com470e71d2011-07-07 08:21:25 +0000987
Erik Språng242e22b2015-05-11 10:17:43 +0200988 SetFlag(kRtcpXrVoipMetric, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200989 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000990}
991
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000992void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200993 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
994 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000995}
996
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000997bool RTCPSender::RtcpXrReceiverReferenceTime() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200998 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
999 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00001000}
1001
niklase@google.com470e71d2011-07-07 08:21:25 +00001002// no callbacks allowed inside this function
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001003int32_t RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
1004 uint32_t maxBitrateKbit) {
Erik Språng242e22b2015-05-11 10:17:43 +02001005 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +00001006
Erik Språng242e22b2015-05-11 10:17:43 +02001007 if (0 == tmmbr_help_.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit)) {
1008 SetFlag(kRtcpTmmbn, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001009 return 0;
1010 }
1011 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001012}
Erik Språng61be2a42015-04-27 13:32:52 +02001013
Erik Språng242e22b2015-05-11 10:17:43 +02001014void RTCPSender::SetFlag(RTCPPacketType type, bool is_volatile) {
1015 report_flags_.insert(ReportFlag(type, is_volatile));
1016}
1017
1018void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
1019 bool is_volatile) {
1020 for (RTCPPacketType type : types)
1021 SetFlag(type, is_volatile);
1022}
1023
1024bool RTCPSender::IsFlagPresent(RTCPPacketType type) const {
1025 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
1026}
1027
1028bool RTCPSender::ConsumeFlag(RTCPPacketType type, bool forced) {
1029 auto it = report_flags_.find(ReportFlag(type, false));
1030 if (it == report_flags_.end())
1031 return false;
1032 if (it->is_volatile || forced)
1033 report_flags_.erase((it));
1034 return true;
1035}
1036
1037bool RTCPSender::AllVolatileFlagsConsumed() const {
1038 for (const ReportFlag& flag : report_flags_) {
1039 if (flag.is_volatile)
1040 return false;
1041 }
1042 return true;
1043}
1044
sprang233bd872015-09-08 13:25:16 -07001045bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
sprang233bd872015-09-08 13:25:16 -07001046 class Sender : public rtcp::RtcpPacket::PacketReadyCallback {
1047 public:
danilchap6db6cdc2015-12-15 02:54:47 -08001048 explicit Sender(Transport* transport)
Peter Boströmac547a62015-09-17 23:03:57 +02001049 : transport_(transport), send_failure_(false) {}
sprang233bd872015-09-08 13:25:16 -07001050
1051 void OnPacketReady(uint8_t* data, size_t length) override {
pbos2d566682015-09-28 09:59:31 -07001052 if (!transport_->SendRtcp(data, length))
sprang233bd872015-09-08 13:25:16 -07001053 send_failure_ = true;
1054 }
1055
1056 Transport* const transport_;
sprang233bd872015-09-08 13:25:16 -07001057 bool send_failure_;
sprang86fd9ed2015-09-29 04:45:43 -07001058 } sender(transport_);
sprang233bd872015-09-08 13:25:16 -07001059
1060 uint8_t buffer[IP_PACKET_SIZE];
1061 return packet.BuildExternalBuffer(buffer, IP_PACKET_SIZE, &sender) &&
1062 !sender.send_failure_;
1063}
1064
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001065} // namespace webrtc