blob: 848d73b2c45b62a2485670ab470bf594a51bcb65 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000011#include "webrtc/modules/rtp_rtcp/source/rtcp_sender.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000013#include <assert.h> // assert
stefan@webrtc.org9354cc92012-06-07 08:10:14 +000014#include <string.h> // memcpy
niklase@google.com470e71d2011-07-07 08:21:25 +000015
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000016#include <algorithm> // min
Erik Språng61be2a42015-04-27 13:32:52 +020017#include <limits> // max
danilchapb8b6fbb2015-12-10 05:05:27 -080018#include <utility>
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000019
Erik Språng61be2a42015-04-27 13:32:52 +020020#include "webrtc/base/checks.h"
Peter Boströmebc0b4e2015-10-28 16:39:33 +010021#include "webrtc/base/logging.h"
tommie4f96502015-10-20 23:00:48 -070022#include "webrtc/base/trace_event.h"
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000023#include "webrtc/common_types.h"
sprang@webrtc.org779c3d12015-03-17 16:42:49 +000024#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
danilchap0219c9b2015-11-18 05:56:53 -080025#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/app.h"
danilchap50c51362015-11-22 09:03:11 -080026#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/bye.h"
danilchap2f7dea12016-01-13 02:03:04 -080027#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/compound_packet.h"
danilchapa8890a52015-12-22 03:43:04 -080028#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/nack.h"
danilchapf8385ad2015-11-27 05:36:09 -080029#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/pli.h"
Danil Chapovalov97f7e132015-12-04 16:13:30 +010030#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
danilchap92e677a2016-01-12 10:04:52 -080031#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sli.h"
danilchapef3d8052016-01-11 03:31:08 -080032#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbn.h"
danilchap7e8145f2016-01-11 11:49:19 -080033#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbr.h"
sprang233bd872015-09-08 13:25:16 -070034#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
tommie4f96502015-10-20 23:00:48 -070035#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010036#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000037
niklase@google.com470e71d2011-07-07 08:21:25 +000038namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000039
40using RTCPUtility::RTCPCnameInformation;
41
Erik Språng61be2a42015-04-27 13:32:52 +020042NACKStringBuilder::NACKStringBuilder()
danilchap162abd32015-12-10 02:39:40 -080043 : stream_(""), count_(0), prevNack_(0), consecutive_(false) {}
edjee@google.com79b02892013-04-04 19:43:34 +000044
pbos@webrtc.orgf3e4cee2013-07-31 15:17:19 +000045NACKStringBuilder::~NACKStringBuilder() {}
46
danilchap162abd32015-12-10 02:39:40 -080047void NACKStringBuilder::PushNACK(uint16_t nack) {
Erik Språng242e22b2015-05-11 10:17:43 +020048 if (count_ == 0) {
49 stream_ << nack;
50 } else if (nack == prevNack_ + 1) {
51 consecutive_ = true;
Erik Språng61be2a42015-04-27 13:32:52 +020052 } else {
Erik Språng242e22b2015-05-11 10:17:43 +020053 if (consecutive_) {
54 stream_ << "-" << prevNack_;
55 consecutive_ = false;
edjee@google.com79b02892013-04-04 19:43:34 +000056 }
Erik Språng242e22b2015-05-11 10:17:43 +020057 stream_ << "," << nack;
Erik Språng61be2a42015-04-27 13:32:52 +020058 }
Erik Språng242e22b2015-05-11 10:17:43 +020059 count_++;
60 prevNack_ = nack;
edjee@google.com79b02892013-04-04 19:43:34 +000061}
62
Erik Språng61be2a42015-04-27 13:32:52 +020063std::string NACKStringBuilder::GetResult() {
Erik Språng242e22b2015-05-11 10:17:43 +020064 if (consecutive_) {
65 stream_ << "-" << prevNack_;
66 consecutive_ = false;
Erik Språng61be2a42015-04-27 13:32:52 +020067 }
Erik Språng242e22b2015-05-11 10:17:43 +020068 return stream_.str();
edjee@google.com79b02892013-04-04 19:43:34 +000069}
70
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000071RTCPSender::FeedbackState::FeedbackState()
72 : send_payload_type(0),
73 frequency_hz(0),
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +000074 packets_sent(0),
75 media_bytes_sent(0),
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000076 send_bitrate(0),
77 last_rr_ntp_secs(0),
78 last_rr_ntp_frac(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000079 remote_sr(0),
Erik Språng61be2a42015-04-27 13:32:52 +020080 has_last_xr_rr(false),
danilchap162abd32015-12-10 02:39:40 -080081 module(nullptr) {}
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000082
danilchap2f7dea12016-01-13 02:03:04 -080083class PacketContainer : public rtcp::CompoundPacket,
Erik Språngf7c57762015-12-04 10:40:35 +010084 public rtcp::RtcpPacket::PacketReadyCallback {
85 public:
86 explicit PacketContainer(Transport* transport)
87 : transport_(transport), bytes_sent_(0) {}
88 virtual ~PacketContainer() {
89 for (RtcpPacket* packet : appended_packets_)
90 delete packet;
91 }
92
93 void OnPacketReady(uint8_t* data, size_t length) override {
94 if (transport_->SendRtcp(data, length))
95 bytes_sent_ += length;
96 }
97
98 size_t SendPackets() {
danilchap2f7dea12016-01-13 02:03:04 -080099 rtcp::CompoundPacket::Build(this);
Erik Språngf7c57762015-12-04 10:40:35 +0100100 return bytes_sent_;
101 }
102
103 private:
104 Transport* transport_;
105 size_t bytes_sent_;
106};
107
108class RTCPSender::RtcpContext {
109 public:
Erik Språng242e22b2015-05-11 10:17:43 +0200110 RtcpContext(const FeedbackState& feedback_state,
111 int32_t nack_size,
112 const uint16_t* nack_list,
113 bool repeat,
114 uint64_t picture_id,
Erik Språngf7c57762015-12-04 10:40:35 +0100115 uint32_t ntp_sec,
116 uint32_t ntp_frac,
117 PacketContainer* container)
118 : feedback_state_(feedback_state),
119 nack_size_(nack_size),
120 nack_list_(nack_list),
121 repeat_(repeat),
122 picture_id_(picture_id),
123 ntp_sec_(ntp_sec),
124 ntp_frac_(ntp_frac),
125 container_(container) {}
Erik Språng242e22b2015-05-11 10:17:43 +0200126
Erik Språngf7c57762015-12-04 10:40:35 +0100127 virtual ~RtcpContext() {}
Erik Språng242e22b2015-05-11 10:17:43 +0200128
Erik Språngf7c57762015-12-04 10:40:35 +0100129 const FeedbackState& feedback_state_;
130 const int32_t nack_size_;
131 const uint16_t* nack_list_;
132 const bool repeat_;
133 const uint64_t picture_id_;
134 const uint32_t ntp_sec_;
135 const uint32_t ntp_frac_;
Erik Språng242e22b2015-05-11 10:17:43 +0200136
Erik Språngf7c57762015-12-04 10:40:35 +0100137 PacketContainer* const container_;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200138};
139
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000140RTCPSender::RTCPSender(
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000141 bool audio,
142 Clock* clock,
143 ReceiveStatistics* receive_statistics,
sprang86fd9ed2015-09-29 04:45:43 -0700144 RtcpPacketTypeCounterObserver* packet_type_counter_observer,
145 Transport* outgoing_transport)
Peter Boströmac547a62015-09-17 23:03:57 +0200146 : audio_(audio),
Erik Språng242e22b2015-05-11 10:17:43 +0200147 clock_(clock),
danilchap47a740b2015-12-15 00:30:07 -0800148 random_(clock_->TimeInMicroseconds()),
pbosda903ea2015-10-02 02:36:56 -0700149 method_(RtcpMode::kOff),
sprang86fd9ed2015-09-29 04:45:43 -0700150 transport_(outgoing_transport),
niklase@google.com470e71d2011-07-07 08:21:25 +0000151
Erik Språng242e22b2015-05-11 10:17:43 +0200152 critical_section_rtcp_sender_(
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000153 CriticalSectionWrapper::CreateCriticalSection()),
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) {
Erik Språng242e22b2015-05-11 10:17:43 +0200180 memset(last_send_report_, 0, sizeof(last_send_report_));
181 memset(last_rtcp_time_, 0, sizeof(last_rtcp_time_));
sprang86fd9ed2015-09-29 04:45:43 -0700182 RTC_DCHECK(transport_ != nullptr);
Erik Språng242e22b2015-05-11 10:17:43 +0200183
184 builders_[kRtcpSr] = &RTCPSender::BuildSR;
185 builders_[kRtcpRr] = &RTCPSender::BuildRR;
Erik Språng0ea42d32015-06-25 14:46:16 +0200186 builders_[kRtcpSdes] = &RTCPSender::BuildSDES;
Erik Språng242e22b2015-05-11 10:17:43 +0200187 builders_[kRtcpPli] = &RTCPSender::BuildPLI;
188 builders_[kRtcpFir] = &RTCPSender::BuildFIR;
189 builders_[kRtcpSli] = &RTCPSender::BuildSLI;
190 builders_[kRtcpRpsi] = &RTCPSender::BuildRPSI;
191 builders_[kRtcpRemb] = &RTCPSender::BuildREMB;
192 builders_[kRtcpBye] = &RTCPSender::BuildBYE;
193 builders_[kRtcpApp] = &RTCPSender::BuildAPP;
194 builders_[kRtcpTmmbr] = &RTCPSender::BuildTMMBR;
195 builders_[kRtcpTmmbn] = &RTCPSender::BuildTMMBN;
196 builders_[kRtcpNack] = &RTCPSender::BuildNACK;
197 builders_[kRtcpXrVoipMetric] = &RTCPSender::BuildVoIPMetric;
198 builders_[kRtcpXrReceiverReferenceTime] =
199 &RTCPSender::BuildReceiverReferenceTime;
200 builders_[kRtcpXrDlrrReportBlock] = &RTCPSender::BuildDlrr;
niklase@google.com470e71d2011-07-07 08:21:25 +0000201}
202
danilchap162abd32015-12-10 02:39:40 -0800203RTCPSender::~RTCPSender() {}
niklase@google.com470e71d2011-07-07 08:21:25 +0000204
pbosda903ea2015-10-02 02:36:56 -0700205RtcpMode RTCPSender::Status() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200206 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
207 return method_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000208}
209
pbosda903ea2015-10-02 02:36:56 -0700210void RTCPSender::SetRTCPStatus(RtcpMode method) {
Erik Språng242e22b2015-05-11 10:17:43 +0200211 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
212 method_ = method;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000213
pbosda903ea2015-10-02 02:36:56 -0700214 if (method == RtcpMode::kOff)
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000215 return;
Erik Språng242e22b2015-05-11 10:17:43 +0200216 next_time_to_send_rtcp_ =
217 clock_->TimeInMilliseconds() +
218 (audio_ ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000219}
220
Erik Språng61be2a42015-04-27 13:32:52 +0200221bool RTCPSender::Sending() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200222 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
223 return sending_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000224}
225
Erik Språng61be2a42015-04-27 13:32:52 +0200226int32_t RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
227 bool sending) {
228 bool sendRTCPBye = false;
229 {
Erik Språng242e22b2015-05-11 10:17:43 +0200230 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000231
pbosda903ea2015-10-02 02:36:56 -0700232 if (method_ != RtcpMode::kOff) {
Erik Språng242e22b2015-05-11 10:17:43 +0200233 if (sending == false && sending_ == true) {
Erik Språng61be2a42015-04-27 13:32:52 +0200234 // Trigger RTCP bye
235 sendRTCPBye = true;
236 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000237 }
Erik Språng242e22b2015-05-11 10:17:43 +0200238 sending_ = sending;
Erik Språng61be2a42015-04-27 13:32:52 +0200239 }
240 if (sendRTCPBye)
241 return SendRTCP(feedback_state, kRtcpBye);
242 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000243}
244
Erik Språng61be2a42015-04-27 13:32:52 +0200245bool RTCPSender::REMB() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200246 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
247 return remb_enabled_;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000248}
249
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000250void RTCPSender::SetREMBStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200251 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
252 remb_enabled_ = enable;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000253}
254
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000255void RTCPSender::SetREMBData(uint32_t bitrate,
256 const std::vector<uint32_t>& ssrcs) {
Erik Språng242e22b2015-05-11 10:17:43 +0200257 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
258 remb_bitrate_ = bitrate;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000259 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000260
Erik Språng242e22b2015-05-11 10:17:43 +0200261 if (remb_enabled_)
262 SetFlag(kRtcpRemb, false);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000263 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
264 // throttled by the caller.
Erik Språng242e22b2015-05-11 10:17:43 +0200265 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000266}
267
Erik Språng61be2a42015-04-27 13:32:52 +0200268bool RTCPSender::TMMBR() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200269 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
270 return IsFlagPresent(RTCPPacketType::kRtcpTmmbr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000271}
272
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000273void RTCPSender::SetTMMBRStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200274 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
275 if (enable) {
276 SetFlag(RTCPPacketType::kRtcpTmmbr, false);
277 } else {
278 ConsumeFlag(RTCPPacketType::kRtcpTmmbr, true);
279 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000280}
281
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000282void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
Erik Språng242e22b2015-05-11 10:17:43 +0200283 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000284 start_timestamp_ = start_timestamp;
285}
286
287void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
288 int64_t capture_time_ms) {
Erik Språng242e22b2015-05-11 10:17:43 +0200289 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000290 last_rtp_timestamp_ = rtp_timestamp;
291 if (capture_time_ms < 0) {
292 // We don't currently get a capture time from VoiceEngine.
Erik Språng242e22b2015-05-11 10:17:43 +0200293 last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000294 } else {
295 last_frame_capture_time_ms_ = capture_time_ms;
296 }
297}
298
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000299void RTCPSender::SetSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200300 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000301
Erik Språng242e22b2015-05-11 10:17:43 +0200302 if (ssrc_ != 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200303 // not first SetSSRC, probably due to a collision
304 // schedule a new RTCP report
305 // make sure that we send a RTP packet
Erik Språng242e22b2015-05-11 10:17:43 +0200306 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
Erik Språng61be2a42015-04-27 13:32:52 +0200307 }
Erik Språng242e22b2015-05-11 10:17:43 +0200308 ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000309}
310
Erik Språng61be2a42015-04-27 13:32:52 +0200311void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200312 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
313 remote_ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000314}
315
Peter Boström9ba52f82015-06-01 14:12:28 +0200316int32_t RTCPSender::SetCNAME(const char* c_name) {
317 if (!c_name)
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000318 return -1;
319
henrikg91d6ede2015-09-17 00:24:34 -0700320 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
Erik Språng242e22b2015-05-11 10:17:43 +0200321 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200322 cname_ = c_name;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000323 return 0;
324}
325
Erik Språng0ea42d32015-06-25 14:46:16 +0200326int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC, const char* c_name) {
327 assert(c_name);
henrikg91d6ede2015-09-17 00:24:34 -0700328 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
Erik Språng242e22b2015-05-11 10:17:43 +0200329 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200330 if (csrc_cnames_.size() >= kRtpCsrcSize)
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000331 return -1;
Erik Språng0ea42d32015-06-25 14:46:16 +0200332
333 csrc_cnames_[SSRC] = c_name;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000334 return 0;
335}
336
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000337int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
Erik Språng242e22b2015-05-11 10:17:43 +0200338 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200339 auto it = csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000340
Erik Språng242e22b2015-05-11 10:17:43 +0200341 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000342 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200343
Erik Språng242e22b2015-05-11 10:17:43 +0200344 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000345 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000346}
347
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000348bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
danilchap162abd32015-12-10 02:39:40 -0800349 /*
350 For audio we use a fix 5 sec interval
niklase@google.com470e71d2011-07-07 08:21:25 +0000351
danilchap162abd32015-12-10 02:39:40 -0800352 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
353 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
354 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000355
356
danilchap162abd32015-12-10 02:39:40 -0800357 From RFC 3550
niklase@google.com470e71d2011-07-07 08:21:25 +0000358
danilchap162abd32015-12-10 02:39:40 -0800359 MAX RTCP BW is 5% if the session BW
360 A send report is approximately 65 bytes inc CNAME
361 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000362
danilchap162abd32015-12-10 02:39:40 -0800363 The RECOMMENDED value for the reduced minimum in seconds is 360
364 divided by the session bandwidth in kilobits/second. This minimum
365 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
niklase@google.com470e71d2011-07-07 08:21:25 +0000366
danilchap162abd32015-12-10 02:39:40 -0800367 If the participant has not yet sent an RTCP packet (the variable
368 initial is true), the constant Tmin is set to 2.5 seconds, else it
369 is set to 5 seconds.
niklase@google.com470e71d2011-07-07 08:21:25 +0000370
danilchap162abd32015-12-10 02:39:40 -0800371 The interval between RTCP packets is varied randomly over the
372 range [0.5,1.5] times the calculated interval to avoid unintended
373 synchronization of all participants
niklase@google.com470e71d2011-07-07 08:21:25 +0000374
danilchap162abd32015-12-10 02:39:40 -0800375 if we send
376 If the participant is a sender (we_sent true), the constant C is
377 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
378 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
379 number of senders.
niklase@google.com470e71d2011-07-07 08:21:25 +0000380
danilchap162abd32015-12-10 02:39:40 -0800381 if we receive only
382 If we_sent is not true, the constant C is set
383 to the average RTCP packet size divided by 75% of the RTCP
384 bandwidth. The constant n is set to the number of receivers
385 (members - senders). If the number of senders is greater than
386 25%, senders and receivers are treated together.
niklase@google.com470e71d2011-07-07 08:21:25 +0000387
danilchap162abd32015-12-10 02:39:40 -0800388 reconsideration NOT required for peer-to-peer
389 "timer reconsideration" is
390 employed. This algorithm implements a simple back-off mechanism
391 which causes users to hold back RTCP packet transmission if the
392 group sizes are increasing.
niklase@google.com470e71d2011-07-07 08:21:25 +0000393
danilchap162abd32015-12-10 02:39:40 -0800394 n = number of members
395 C = avg_size/(rtcpBW/4)
niklase@google.com470e71d2011-07-07 08:21:25 +0000396
danilchap162abd32015-12-10 02:39:40 -0800397 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
niklase@google.com470e71d2011-07-07 08:21:25 +0000398
danilchap162abd32015-12-10 02:39:40 -0800399 4. The calculated interval T is set to a number uniformly distributed
400 between 0.5 and 1.5 times the deterministic calculated interval.
niklase@google.com470e71d2011-07-07 08:21:25 +0000401
danilchap162abd32015-12-10 02:39:40 -0800402 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
403 for the fact that the timer reconsideration algorithm converges to
404 a value of the RTCP bandwidth below the intended average
405 */
niklase@google.com470e71d2011-07-07 08:21:25 +0000406
Erik Språng242e22b2015-05-11 10:17:43 +0200407 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000408
Erik Språng242e22b2015-05-11 10:17:43 +0200409 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
xians@webrtc.org8738d272011-11-25 13:43:53 +0000410
pbosda903ea2015-10-02 02:36:56 -0700411 if (method_ == RtcpMode::kOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000412 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000413
Erik Språng242e22b2015-05-11 10:17:43 +0200414 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200415 // for video key-frames we want to send the RTCP before the large key-frame
416 // if we have a 100 ms margin
417 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
418 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000419
Erik Språng242e22b2015-05-11 10:17:43 +0200420 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200421 return true;
422 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200423 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200424 // wrap
425 return true;
426 }
427 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000428}
429
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000430int64_t RTCPSender::SendTimeOfSendReport(uint32_t sendReport) {
Erik Språng242e22b2015-05-11 10:17:43 +0200431 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000432
Erik Språng61be2a42015-04-27 13:32:52 +0200433 // This is only saved when we are the sender
Erik Språng242e22b2015-05-11 10:17:43 +0200434 if ((last_send_report_[0] == 0) || (sendReport == 0)) {
Erik Språng61be2a42015-04-27 13:32:52 +0200435 return 0; // will be ignored
436 } else {
437 for (int i = 0; i < RTCP_NUMBER_OF_SR; ++i) {
Erik Språng242e22b2015-05-11 10:17:43 +0200438 if (last_send_report_[i] == sendReport)
439 return last_rtcp_time_[i];
niklase@google.com470e71d2011-07-07 08:21:25 +0000440 }
Erik Språng61be2a42015-04-27 13:32:52 +0200441 }
442 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000443}
444
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000445bool RTCPSender::SendTimeOfXrRrReport(uint32_t mid_ntp,
446 int64_t* time_ms) const {
Erik Språng242e22b2015-05-11 10:17:43 +0200447 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000448
449 if (last_xr_rr_.empty()) {
450 return false;
451 }
452 std::map<uint32_t, int64_t>::const_iterator it = last_xr_rr_.find(mid_ntp);
453 if (it == last_xr_rr_.end()) {
454 return false;
455 }
456 *time_ms = it->second;
457 return true;
458}
459
Erik Språngf7c57762015-12-04 10:40:35 +0100460rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildSR(const RtcpContext& ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200461 for (int i = (RTCP_NUMBER_OF_SR - 2); i >= 0; i--) {
462 // shift old
Erik Språng242e22b2015-05-11 10:17:43 +0200463 last_send_report_[i + 1] = last_send_report_[i];
464 last_rtcp_time_[i + 1] = last_rtcp_time_[i];
Erik Språng61be2a42015-04-27 13:32:52 +0200465 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000466
Erik Språngf7c57762015-12-04 10:40:35 +0100467 last_rtcp_time_[0] = Clock::NtpToMs(ctx.ntp_sec_, ctx.ntp_frac_);
468 last_send_report_[0] = (ctx.ntp_sec_ << 16) + (ctx.ntp_frac_ >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000469
Erik Språng61be2a42015-04-27 13:32:52 +0200470 // The timestamp of this RTCP packet should be estimated as the timestamp of
471 // the frame being captured at this moment. We are calculating that
472 // timestamp as the last frame's timestamp + the time since the last frame
473 // was captured.
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200474 uint32_t rtp_timestamp =
475 start_timestamp_ + last_rtp_timestamp_ +
476 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) *
Erik Språngf7c57762015-12-04 10:40:35 +0100477 (ctx.feedback_state_.frequency_hz / 1000);
niklase@google.com470e71d2011-07-07 08:21:25 +0000478
Erik Språngf7c57762015-12-04 10:40:35 +0100479 rtcp::SenderReport* report = new rtcp::SenderReport();
480 report->From(ssrc_);
481 report->WithNtpSec(ctx.ntp_sec_);
482 report->WithNtpFrac(ctx.ntp_frac_);
483 report->WithRtpTimestamp(rtp_timestamp);
484 report->WithPacketCount(ctx.feedback_state_.packets_sent);
485 report->WithOctetCount(ctx.feedback_state_.media_bytes_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000486
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200487 for (auto it : report_blocks_)
Erik Språngf7c57762015-12-04 10:40:35 +0100488 report->WithReportBlock(it.second);
niklase@google.com470e71d2011-07-07 08:21:25 +0000489
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200490 report_blocks_.clear();
Erik Språngf7c57762015-12-04 10:40:35 +0100491
492 return rtc::scoped_ptr<rtcp::SenderReport>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000493}
494
Erik Språngf7c57762015-12-04 10:40:35 +0100495rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildSDES(
496 const RtcpContext& ctx) {
Erik Språng0ea42d32015-06-25 14:46:16 +0200497 size_t length_cname = cname_.length();
henrikg91d6ede2015-09-17 00:24:34 -0700498 RTC_CHECK_LT(length_cname, static_cast<size_t>(RTCP_CNAME_SIZE));
niklase@google.com470e71d2011-07-07 08:21:25 +0000499
Erik Språngf7c57762015-12-04 10:40:35 +0100500 rtcp::Sdes* sdes = new rtcp::Sdes();
501 sdes->WithCName(ssrc_, cname_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200502
503 for (const auto it : csrc_cnames_)
Erik Språngf7c57762015-12-04 10:40:35 +0100504 sdes->WithCName(it.first, it.second);
Erik Språng0ea42d32015-06-25 14:46:16 +0200505
Erik Språngf7c57762015-12-04 10:40:35 +0100506 return rtc::scoped_ptr<rtcp::Sdes>(sdes);
niklase@google.com470e71d2011-07-07 08:21:25 +0000507}
508
Erik Språngf7c57762015-12-04 10:40:35 +0100509rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildRR(const RtcpContext& ctx) {
510 rtcp::ReceiverReport* report = new rtcp::ReceiverReport();
511 report->From(ssrc_);
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200512 for (auto it : report_blocks_)
Erik Språngf7c57762015-12-04 10:40:35 +0100513 report->WithReportBlock(it.second);
Erik Språng61be2a42015-04-27 13:32:52 +0200514
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200515 report_blocks_.clear();
Erik Språngf7c57762015-12-04 10:40:35 +0100516 return rtc::scoped_ptr<rtcp::ReceiverReport>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000517}
518
Erik Språngf7c57762015-12-04 10:40:35 +0100519rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildPLI(const RtcpContext& ctx) {
520 rtcp::Pli* pli = new rtcp::Pli();
521 pli->From(ssrc_);
522 pli->To(remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200523
Erik Språng242e22b2015-05-11 10:17:43 +0200524 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
525 "RTCPSender::PLI");
526 ++packet_type_counter_.pli_packets;
527 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
528 ssrc_, packet_type_counter_.pli_packets);
529
Erik Språngf7c57762015-12-04 10:40:35 +0100530 return rtc::scoped_ptr<rtcp::Pli>(pli);
Erik Språng61be2a42015-04-27 13:32:52 +0200531}
532
Erik Språngf7c57762015-12-04 10:40:35 +0100533rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildFIR(const RtcpContext& ctx) {
534 if (!ctx.repeat_)
sprang62dae192015-08-05 02:35:35 -0700535 ++sequence_number_fir_; // Do not increase if repetition.
niklase@google.com470e71d2011-07-07 08:21:25 +0000536
Erik Språngf7c57762015-12-04 10:40:35 +0100537 rtcp::Fir* fir = new rtcp::Fir();
538 fir->From(ssrc_);
539 fir->To(remote_ssrc_);
540 fir->WithCommandSeqNum(sequence_number_fir_);
Erik Språng242e22b2015-05-11 10:17:43 +0200541
542 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
543 "RTCPSender::FIR");
544 ++packet_type_counter_.fir_packets;
545 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
546 ssrc_, packet_type_counter_.fir_packets);
547
Erik Språngf7c57762015-12-04 10:40:35 +0100548 return rtc::scoped_ptr<rtcp::Fir>(fir);
niklase@google.com470e71d2011-07-07 08:21:25 +0000549}
550
551/*
552 0 1 2 3
553 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
554 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
555 | First | Number | PictureID |
556 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
557*/
Erik Språngf7c57762015-12-04 10:40:35 +0100558rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildSLI(const RtcpContext& ctx) {
559 rtcp::Sli* sli = new rtcp::Sli();
560 sli->From(ssrc_);
561 sli->To(remote_ssrc_);
sprang0365a272015-08-11 01:02:37 -0700562 // Crop picture id to 6 least significant bits.
Erik Språngf7c57762015-12-04 10:40:35 +0100563 sli->WithPictureId(ctx.picture_id_ & 0x3F);
sprang0365a272015-08-11 01:02:37 -0700564
Erik Språngf7c57762015-12-04 10:40:35 +0100565 return rtc::scoped_ptr<rtcp::Sli>(sli);
niklase@google.com470e71d2011-07-07 08:21:25 +0000566}
567
568/*
569 0 1 2 3
570 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
571 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
572 | PB |0| Payload Type| Native RPSI bit string |
573 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
574 | defined per codec ... | Padding (0) |
575 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
576*/
577/*
578* Note: not generic made for VP8
579*/
Erik Språngf7c57762015-12-04 10:40:35 +0100580rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildRPSI(
581 const RtcpContext& ctx) {
582 if (ctx.feedback_state_.send_payload_type == 0xFF)
583 return nullptr;
Erik Språng242e22b2015-05-11 10:17:43 +0200584
Erik Språngf7c57762015-12-04 10:40:35 +0100585 rtcp::Rpsi* rpsi = new rtcp::Rpsi();
586 rpsi->From(ssrc_);
587 rpsi->To(remote_ssrc_);
588 rpsi->WithPayloadType(ctx.feedback_state_.send_payload_type);
589 rpsi->WithPictureId(ctx.picture_id_);
sprangcf7f54d2015-08-13 04:37:42 -0700590
Erik Språngf7c57762015-12-04 10:40:35 +0100591 return rtc::scoped_ptr<rtcp::Rpsi>(rpsi);
niklase@google.com470e71d2011-07-07 08:21:25 +0000592}
593
Erik Språngf7c57762015-12-04 10:40:35 +0100594rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildREMB(
595 const RtcpContext& ctx) {
596 rtcp::Remb* remb = new rtcp::Remb();
597 remb->From(ssrc_);
sprangdd4edc52015-08-21 04:21:51 -0700598 for (uint32_t ssrc : remb_ssrcs_)
Erik Språngf7c57762015-12-04 10:40:35 +0100599 remb->AppliesTo(ssrc);
600 remb->WithBitrateBps(remb_bitrate_);
Erik Språng61be2a42015-04-27 13:32:52 +0200601
Erik Språng242e22b2015-05-11 10:17:43 +0200602 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
603 "RTCPSender::REMB");
604
Erik Språngf7c57762015-12-04 10:40:35 +0100605 return rtc::scoped_ptr<rtcp::Remb>(remb);
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000606}
607
Erik Språng61be2a42015-04-27 13:32:52 +0200608void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
Erik Språng242e22b2015-05-11 10:17:43 +0200609 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
610 tmmbr_send_ = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000611}
612
Erik Språngf7c57762015-12-04 10:40:35 +0100613rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBR(
614 const RtcpContext& ctx) {
615 if (ctx.feedback_state_.module == nullptr)
616 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200617 // Before sending the TMMBR check the received TMMBN, only an owner is
618 // allowed to raise the bitrate:
619 // * If the sender is an owner of the TMMBN -> send TMMBR
620 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000621
Erik Språng61be2a42015-04-27 13:32:52 +0200622 // get current bounding set from RTCP receiver
623 bool tmmbrOwner = false;
624 // store in candidateSet, allocates one extra slot
Erik Språng242e22b2015-05-11 10:17:43 +0200625 TMMBRSet* candidateSet = tmmbr_help_.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000626
Erik Språng242e22b2015-05-11 10:17:43 +0200627 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
628 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
Erik Språng61be2a42015-04-27 13:32:52 +0200629 // since RTCPreceiver is not doing the reverse we should be fine
630 int32_t lengthOfBoundingSet =
danilchap6db6cdc2015-12-15 02:54:47 -0800631 ctx.feedback_state_.module->BoundingSet(&tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +0000632
Erik Språng61be2a42015-04-27 13:32:52 +0200633 if (lengthOfBoundingSet > 0) {
634 for (int32_t i = 0; i < lengthOfBoundingSet; i++) {
Erik Språng242e22b2015-05-11 10:17:43 +0200635 if (candidateSet->Tmmbr(i) == tmmbr_send_ &&
636 candidateSet->PacketOH(i) == packet_oh_send_) {
Erik Språngf7c57762015-12-04 10:40:35 +0100637 // Do not send the same tuple.
638 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200639 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000640 }
Erik Språng61be2a42015-04-27 13:32:52 +0200641 if (!tmmbrOwner) {
642 // use received bounding set as candidate set
643 // add current tuple
Erik Språng242e22b2015-05-11 10:17:43 +0200644 candidateSet->SetEntry(lengthOfBoundingSet, tmmbr_send_, packet_oh_send_,
645 ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200646 int numCandidates = lengthOfBoundingSet + 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000647
Erik Språng61be2a42015-04-27 13:32:52 +0200648 // find bounding set
Erik Språngf7c57762015-12-04 10:40:35 +0100649 TMMBRSet* boundingSet = nullptr;
Erik Språng242e22b2015-05-11 10:17:43 +0200650 int numBoundingSet = tmmbr_help_.FindTMMBRBoundingSet(boundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200651 if (numBoundingSet > 0 || numBoundingSet <= numCandidates)
Erik Språng242e22b2015-05-11 10:17:43 +0200652 tmmbrOwner = tmmbr_help_.IsOwner(ssrc_, numBoundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200653 if (!tmmbrOwner) {
Erik Språngf7c57762015-12-04 10:40:35 +0100654 // Did not enter bounding set, no meaning to send this request.
655 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200656 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000657 }
Erik Språng61be2a42015-04-27 13:32:52 +0200658 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000659
Erik Språngf7c57762015-12-04 10:40:35 +0100660 if (!tmmbr_send_)
661 return nullptr;
sprang81a3e602015-08-21 05:30:11 -0700662
Erik Språngf7c57762015-12-04 10:40:35 +0100663 rtcp::Tmmbr* tmmbr = new rtcp::Tmmbr();
664 tmmbr->From(ssrc_);
665 tmmbr->To(remote_ssrc_);
666 tmmbr->WithBitrateKbps(tmmbr_send_);
667 tmmbr->WithOverhead(packet_oh_send_);
668
669 return rtc::scoped_ptr<rtcp::Tmmbr>(tmmbr);
Erik Språng61be2a42015-04-27 13:32:52 +0200670}
671
Erik Språngf7c57762015-12-04 10:40:35 +0100672rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBN(
673 const RtcpContext& ctx) {
Erik Språng242e22b2015-05-11 10:17:43 +0200674 TMMBRSet* boundingSet = tmmbr_help_.BoundingSetToSend();
Erik Språngf7c57762015-12-04 10:40:35 +0100675 if (boundingSet == nullptr)
676 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200677
Erik Språngf7c57762015-12-04 10:40:35 +0100678 rtcp::Tmmbn* tmmbn = new rtcp::Tmmbn();
679 tmmbn->From(ssrc_);
sprangd83df502015-08-27 01:05:08 -0700680 for (uint32_t i = 0; i < boundingSet->lengthOfSet(); i++) {
681 if (boundingSet->Tmmbr(i) > 0) {
Erik Språngf7c57762015-12-04 10:40:35 +0100682 tmmbn->WithTmmbr(boundingSet->Ssrc(i), boundingSet->Tmmbr(i),
683 boundingSet->PacketOH(i));
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000684 }
Erik Språng61be2a42015-04-27 13:32:52 +0200685 }
sprangd83df502015-08-27 01:05:08 -0700686
Erik Språngf7c57762015-12-04 10:40:35 +0100687 return rtc::scoped_ptr<rtcp::Tmmbn>(tmmbn);
niklase@google.com470e71d2011-07-07 08:21:25 +0000688}
689
Erik Språngf7c57762015-12-04 10:40:35 +0100690rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildAPP(const RtcpContext& ctx) {
691 rtcp::App* app = new rtcp::App();
692 app->From(ssrc_);
693 app->WithSubType(app_sub_type_);
694 app->WithName(app_name_);
695 app->WithData(app_data_.get(), app_length_);
Erik Språng521875a2015-09-01 10:11:16 +0200696
Erik Språngf7c57762015-12-04 10:40:35 +0100697 return rtc::scoped_ptr<rtcp::App>(app);
Erik Språng61be2a42015-04-27 13:32:52 +0200698}
699
Erik Språngf7c57762015-12-04 10:40:35 +0100700rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildNACK(
701 const RtcpContext& ctx) {
702 rtcp::Nack* nack = new rtcp::Nack();
703 nack->From(ssrc_);
704 nack->To(remote_ssrc_);
705 nack->WithList(ctx.nack_list_, ctx.nack_size_);
Erik Språng61be2a42015-04-27 13:32:52 +0200706
707 // Report stats.
708 NACKStringBuilder stringBuilder;
Erik Språngf7c57762015-12-04 10:40:35 +0100709 for (int idx = 0; idx < ctx.nack_size_; ++idx) {
710 stringBuilder.PushNACK(ctx.nack_list_[idx]);
711 nack_stats_.ReportRequest(ctx.nack_list_[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +0200712 }
Erik Språng61be2a42015-04-27 13:32:52 +0200713 packet_type_counter_.nack_requests = nack_stats_.requests();
714 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +0200715
716 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
717 "RTCPSender::NACK", "nacks",
718 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
719 ++packet_type_counter_.nack_packets;
720 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
721 ssrc_, packet_type_counter_.nack_packets);
722
Erik Språngf7c57762015-12-04 10:40:35 +0100723 return rtc::scoped_ptr<rtcp::Nack>(nack);
Erik Språng61be2a42015-04-27 13:32:52 +0200724}
725
Erik Språngf7c57762015-12-04 10:40:35 +0100726rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildBYE(const RtcpContext& ctx) {
727 rtcp::Bye* bye = new rtcp::Bye();
728 bye->From(ssrc_);
sprangd8ee4f92015-08-24 03:25:19 -0700729 for (uint32_t csrc : csrcs_)
Erik Språngf7c57762015-12-04 10:40:35 +0100730 bye->WithCsrc(csrc);
sprangd8ee4f92015-08-24 03:25:19 -0700731
Erik Språngf7c57762015-12-04 10:40:35 +0100732 return rtc::scoped_ptr<rtcp::Bye>(bye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000733}
734
Erik Språngf7c57762015-12-04 10:40:35 +0100735rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildReceiverReferenceTime(
736 const RtcpContext& ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200737 if (last_xr_rr_.size() >= RTCP_NUMBER_OF_SR)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000738 last_xr_rr_.erase(last_xr_rr_.begin());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000739 last_xr_rr_.insert(std::pair<uint32_t, int64_t>(
Erik Språngf7c57762015-12-04 10:40:35 +0100740 RTCPUtility::MidNtp(ctx.ntp_sec_, ctx.ntp_frac_),
741 Clock::NtpToMs(ctx.ntp_sec_, ctx.ntp_frac_)));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000742
Erik Språngf7c57762015-12-04 10:40:35 +0100743 rtcp::Xr* xr = new rtcp::Xr();
744 xr->From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000745
Erik Språngca28fdc2015-08-31 14:00:50 +0200746 rtcp::Rrtr rrtr;
Danil Chapovalovfc47ed62015-12-07 14:46:35 +0100747 rrtr.WithNtp(NtpTime(ctx.ntp_sec_, ctx.ntp_frac_));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000748
Erik Språngf7c57762015-12-04 10:40:35 +0100749 xr->WithRrtr(&rrtr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000750
Erik Språngca28fdc2015-08-31 14:00:50 +0200751 // TODO(sprang): Merge XR report sending to contain all of RRTR, DLRR, VOIP?
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000752
Erik Språngf7c57762015-12-04 10:40:35 +0100753 return rtc::scoped_ptr<rtcp::Xr>(xr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000754}
755
Erik Språngf7c57762015-12-04 10:40:35 +0100756rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildDlrr(
757 const RtcpContext& ctx) {
758 rtcp::Xr* xr = new rtcp::Xr();
759 xr->From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000760
Erik Språngca28fdc2015-08-31 14:00:50 +0200761 rtcp::Dlrr dlrr;
Erik Språngf7c57762015-12-04 10:40:35 +0100762 const RtcpReceiveTimeInfo& info = ctx.feedback_state_.last_xr_rr;
Erik Språngca28fdc2015-08-31 14:00:50 +0200763 dlrr.WithDlrrItem(info.sourceSSRC, info.lastRR, info.delaySinceLastRR);
764
Erik Språngf7c57762015-12-04 10:40:35 +0100765 xr->WithDlrr(&dlrr);
Erik Språngca28fdc2015-08-31 14:00:50 +0200766
Erik Språngf7c57762015-12-04 10:40:35 +0100767 return rtc::scoped_ptr<rtcp::Xr>(xr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000768}
769
Erik Språng242e22b2015-05-11 10:17:43 +0200770// TODO(sprang): Add a unit test for this, or remove if the code isn't used.
Erik Språngf7c57762015-12-04 10:40:35 +0100771rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildVoIPMetric(
772 const RtcpContext& context) {
773 rtcp::Xr* xr = new rtcp::Xr();
774 xr->From(ssrc_);
Erik Språngca28fdc2015-08-31 14:00:50 +0200775
776 rtcp::VoipMetric voip;
777 voip.To(remote_ssrc_);
danilchap91941ae2015-12-15 07:06:36 -0800778 voip.WithVoipMetric(xr_voip_metric_);
Erik Språngca28fdc2015-08-31 14:00:50 +0200779
Erik Språngf7c57762015-12-04 10:40:35 +0100780 xr->WithVoipMetric(&voip);
Erik Språngca28fdc2015-08-31 14:00:50 +0200781
Erik Språngf7c57762015-12-04 10:40:35 +0100782 return rtc::scoped_ptr<rtcp::Xr>(xr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000783}
784
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000785int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200786 RTCPPacketType packetType,
787 int32_t nack_size,
788 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000789 bool repeat,
790 uint64_t pictureID) {
Erik Språng242e22b2015-05-11 10:17:43 +0200791 return SendCompoundRTCP(
792 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
793 nack_size, nack_list, repeat, pictureID);
794}
795
796int32_t RTCPSender::SendCompoundRTCP(
797 const FeedbackState& feedback_state,
Erik Språngf7c57762015-12-04 10:40:35 +0100798 const std::set<RTCPPacketType>& packet_types,
Erik Språng242e22b2015-05-11 10:17:43 +0200799 int32_t nack_size,
800 const uint16_t* nack_list,
801 bool repeat,
802 uint64_t pictureID) {
Erik Språngf7c57762015-12-04 10:40:35 +0100803 PacketContainer container(transport_);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000804 {
Erik Språng242e22b2015-05-11 10:17:43 +0200805 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
pbosda903ea2015-10-02 02:36:56 -0700806 if (method_ == RtcpMode::kOff) {
Erik Språng61be2a42015-04-27 13:32:52 +0200807 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
808 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +0000809 }
Erik Språngf7c57762015-12-04 10:40:35 +0100810
811 // We need to send our NTP even if we haven't received any reports.
812 uint32_t ntp_sec;
813 uint32_t ntp_frac;
814 clock_->CurrentNtp(ntp_sec, ntp_frac);
815 RtcpContext context(feedback_state, nack_size, nack_list, repeat, pictureID,
816 ntp_sec, ntp_frac, &container);
817
818 PrepareReport(packet_types, feedback_state);
819
820 auto it = report_flags_.begin();
821 while (it != report_flags_.end()) {
822 auto builder_it = builders_.find(it->type);
823 RTC_DCHECK(builder_it != builders_.end());
824 if (it->is_volatile) {
825 report_flags_.erase(it++);
826 } else {
827 ++it;
828 }
829
830 BuilderFunc func = builder_it->second;
831 rtc::scoped_ptr<rtcp::RtcpPacket> packet = (this->*func)(context);
832 if (packet.get() == nullptr)
833 return -1;
834 container.Append(packet.release());
835 }
836
837 if (packet_type_counter_observer_ != nullptr) {
838 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
839 remote_ssrc_, packet_type_counter_);
840 }
841
842 RTC_DCHECK(AllVolatileFlagsConsumed());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000843 }
Erik Språng61be2a42015-04-27 13:32:52 +0200844
Erik Språngf7c57762015-12-04 10:40:35 +0100845 size_t bytes_sent = container.SendPackets();
846 return bytes_sent == 0 ? -1 : 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000847}
848
Erik Språngf7c57762015-12-04 10:40:35 +0100849void RTCPSender::PrepareReport(const std::set<RTCPPacketType>& packetTypes,
850 const FeedbackState& feedback_state) {
Erik Språng242e22b2015-05-11 10:17:43 +0200851 // Add all flags as volatile. Non volatile entries will not be overwritten
852 // and all new volatile flags added will be consumed by the end of this call.
853 SetFlags(packetTypes, true);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000854
Erik Språng61be2a42015-04-27 13:32:52 +0200855 if (packet_type_counter_.first_packet_time_ms == -1)
Erik Språng242e22b2015-05-11 10:17:43 +0200856 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språng61be2a42015-04-27 13:32:52 +0200857
Erik Språng242e22b2015-05-11 10:17:43 +0200858 bool generate_report;
859 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
860 // Report type already explicitly set, don't automatically populate.
861 generate_report = true;
henrikg91d6ede2015-09-17 00:24:34 -0700862 RTC_DCHECK(ConsumeFlag(kRtcpReport) == false);
Erik Språng242e22b2015-05-11 10:17:43 +0200863 } else {
864 generate_report =
pbosda903ea2015-10-02 02:36:56 -0700865 (ConsumeFlag(kRtcpReport) && method_ == RtcpMode::kReducedSize) ||
866 method_ == RtcpMode::kCompound;
Erik Språng242e22b2015-05-11 10:17:43 +0200867 if (generate_report)
868 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000869 }
870
Erik Språng0ea42d32015-06-25 14:46:16 +0200871 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
Erik Språng242e22b2015-05-11 10:17:43 +0200872 SetFlag(kRtcpSdes, true);
873
Erik Språng242e22b2015-05-11 10:17:43 +0200874 if (generate_report) {
875 if (!sending_ && xr_send_receiver_reference_time_enabled_)
876 SetFlag(kRtcpXrReceiverReferenceTime, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200877 if (feedback_state.has_last_xr_rr)
Erik Språng242e22b2015-05-11 10:17:43 +0200878 SetFlag(kRtcpXrDlrrReportBlock, true);
879
880 // generate next time to send an RTCP report
danilchap47a740b2015-12-15 00:30:07 -0800881 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000882
danilchap47a740b2015-12-15 00:30:07 -0800883 if (!audio_) {
Erik Språng242e22b2015-05-11 10:17:43 +0200884 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200885 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
886 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
887 if (send_bitrate_kbit != 0)
888 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000889 }
Erik Språng61be2a42015-04-27 13:32:52 +0200890 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
891 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
Erik Språng61be2a42015-04-27 13:32:52 +0200892 }
danilchap47a740b2015-12-15 00:30:07 -0800893 // The interval between RTCP packets is varied randomly over the
894 // range [1/2,3/2] times the calculated interval.
895 uint32_t timeToNext =
896 random_.Rand(minIntervalMs * 1 / 2, minIntervalMs * 3 / 2);
Erik Språng242e22b2015-05-11 10:17:43 +0200897 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000898
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000899 StatisticianMap statisticians =
900 receive_statistics_->GetActiveStatisticians();
danilchapa72e7342015-12-22 08:07:45 -0800901 RTC_DCHECK(report_blocks_.empty());
902 for (auto& it : statisticians) {
903 AddReportBlock(feedback_state, it.first, it.second);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000904 }
905 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000906}
907
danilchapa72e7342015-12-22 08:07:45 -0800908bool RTCPSender::AddReportBlock(const FeedbackState& feedback_state,
909 uint32_t ssrc,
910 StreamStatistician* statistician) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000911 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000912 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000913 if (!statistician->GetStatistics(&stats, true))
914 return false;
danilchapa72e7342015-12-22 08:07:45 -0800915
916 if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) {
917 LOG(LS_WARNING) << "Too many report blocks.";
918 return false;
919 }
920 RTC_DCHECK(report_blocks_.find(ssrc) == report_blocks_.end());
921 rtcp::ReportBlock* block = &report_blocks_[ssrc];
922 block->To(ssrc);
923 block->WithFractionLost(stats.fraction_lost);
924 if (!block->WithCumulativeLost(stats.cumulative_lost)) {
925 report_blocks_.erase(ssrc);
926 LOG(LS_WARNING) << "Cumulative lost is oversized.";
927 return false;
928 }
929 block->WithExtHighestSeqNum(stats.extended_max_sequence_number);
930 block->WithJitter(stats.jitter);
931 block->WithLastSr(feedback_state.remote_sr);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000932
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200933 // TODO(sprang): Do we really need separate time stamps for each report?
934 // Get our NTP as late as possible to avoid a race.
935 uint32_t ntp_secs;
936 uint32_t ntp_frac;
937 clock_->CurrentNtp(ntp_secs, ntp_frac);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000938
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200939 // Delay since last received report.
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000940 if ((feedback_state.last_rr_ntp_secs != 0) ||
941 (feedback_state.last_rr_ntp_frac != 0)) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200942 // Get the 16 lowest bits of seconds and the 16 highest bits of fractions.
943 uint32_t now = ntp_secs & 0x0000FFFF;
Erik Språng61be2a42015-04-27 13:32:52 +0200944 now <<= 16;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200945 now += (ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000946
Erik Språng61be2a42015-04-27 13:32:52 +0200947 uint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
948 receiveTime <<= 16;
949 receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000950
danilchapa72e7342015-12-22 08:07:45 -0800951 block->WithDelayLastSr(now - receiveTime);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000952 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000953 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000954}
955
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000956void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
957 assert(csrcs.size() <= kRtpCsrcSize);
Erik Språng242e22b2015-05-11 10:17:43 +0200958 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000959 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +0000960}
961
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000962int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
963 uint32_t name,
964 const uint8_t* data,
965 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +0200966 if (length % 4 != 0) {
967 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
968 return -1;
969 }
Erik Språng242e22b2015-05-11 10:17:43 +0200970 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000971
Erik Språng242e22b2015-05-11 10:17:43 +0200972 SetFlag(kRtcpApp, true);
973 app_sub_type_ = subType;
974 app_name_ = name;
975 app_data_.reset(new uint8_t[length]);
976 app_length_ = length;
977 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +0200978 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000979}
980
Erik Språng61be2a42015-04-27 13:32:52 +0200981int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
Erik Språng242e22b2015-05-11 10:17:43 +0200982 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
983 memcpy(&xr_voip_metric_, VoIPMetric, sizeof(RTCPVoIPMetric));
niklase@google.com470e71d2011-07-07 08:21:25 +0000984
Erik Språng242e22b2015-05-11 10:17:43 +0200985 SetFlag(kRtcpXrVoipMetric, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200986 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000987}
988
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000989void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200990 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
991 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000992}
993
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000994bool RTCPSender::RtcpXrReceiverReferenceTime() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200995 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
996 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000997}
998
niklase@google.com470e71d2011-07-07 08:21:25 +0000999// no callbacks allowed inside this function
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001000int32_t RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
1001 uint32_t maxBitrateKbit) {
Erik Språng242e22b2015-05-11 10:17:43 +02001002 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +00001003
Erik Språng242e22b2015-05-11 10:17:43 +02001004 if (0 == tmmbr_help_.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit)) {
1005 SetFlag(kRtcpTmmbn, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001006 return 0;
1007 }
1008 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001009}
Erik Språng61be2a42015-04-27 13:32:52 +02001010
Erik Språng242e22b2015-05-11 10:17:43 +02001011void RTCPSender::SetFlag(RTCPPacketType type, bool is_volatile) {
1012 report_flags_.insert(ReportFlag(type, is_volatile));
1013}
1014
1015void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
1016 bool is_volatile) {
1017 for (RTCPPacketType type : types)
1018 SetFlag(type, is_volatile);
1019}
1020
1021bool RTCPSender::IsFlagPresent(RTCPPacketType type) const {
1022 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
1023}
1024
1025bool RTCPSender::ConsumeFlag(RTCPPacketType type, bool forced) {
1026 auto it = report_flags_.find(ReportFlag(type, false));
1027 if (it == report_flags_.end())
1028 return false;
1029 if (it->is_volatile || forced)
1030 report_flags_.erase((it));
1031 return true;
1032}
1033
1034bool RTCPSender::AllVolatileFlagsConsumed() const {
1035 for (const ReportFlag& flag : report_flags_) {
1036 if (flag.is_volatile)
1037 return false;
1038 }
1039 return true;
1040}
1041
sprang233bd872015-09-08 13:25:16 -07001042bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
sprang233bd872015-09-08 13:25:16 -07001043 class Sender : public rtcp::RtcpPacket::PacketReadyCallback {
1044 public:
danilchap6db6cdc2015-12-15 02:54:47 -08001045 explicit Sender(Transport* transport)
Peter Boströmac547a62015-09-17 23:03:57 +02001046 : transport_(transport), send_failure_(false) {}
sprang233bd872015-09-08 13:25:16 -07001047
1048 void OnPacketReady(uint8_t* data, size_t length) override {
pbos2d566682015-09-28 09:59:31 -07001049 if (!transport_->SendRtcp(data, length))
sprang233bd872015-09-08 13:25:16 -07001050 send_failure_ = true;
1051 }
1052
1053 Transport* const transport_;
sprang233bd872015-09-08 13:25:16 -07001054 bool send_failure_;
sprang86fd9ed2015-09-29 04:45:43 -07001055 } sender(transport_);
sprang233bd872015-09-08 13:25:16 -07001056
1057 uint8_t buffer[IP_PACKET_SIZE];
1058 return packet.BuildExternalBuffer(buffer, IP_PACKET_SIZE, &sender) &&
1059 !sender.send_failure_;
1060}
1061
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001062} // namespace webrtc