blob: 69b0ae1a2ffe969ece7aa49d218163b281fe034e [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 Chapovalov5679da12016-01-15 13:19:53 +010028#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/fir.h"
danilchapa8890a52015-12-22 03:43:04 -080029#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/nack.h"
danilchapf8385ad2015-11-27 05:36:09 -080030#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/pli.h"
Danil Chapovalov97f7e132015-12-04 16:13:30 +010031#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
Danil Chapovalova5eba6c2016-01-15 12:40:15 +010032#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/remb.h"
danilchap92e677a2016-01-12 10:04:52 -080033#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sli.h"
danilchapef3d8052016-01-11 03:31:08 -080034#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbn.h"
danilchap7e8145f2016-01-11 11:49:19 -080035#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbr.h"
sprang233bd872015-09-08 13:25:16 -070036#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
tommie4f96502015-10-20 23:00:48 -070037#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010038#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000039
niklase@google.com470e71d2011-07-07 08:21:25 +000040namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000041
42using RTCPUtility::RTCPCnameInformation;
43
Erik Språng61be2a42015-04-27 13:32:52 +020044NACKStringBuilder::NACKStringBuilder()
danilchap162abd32015-12-10 02:39:40 -080045 : stream_(""), count_(0), prevNack_(0), consecutive_(false) {}
edjee@google.com79b02892013-04-04 19:43:34 +000046
pbos@webrtc.orgf3e4cee2013-07-31 15:17:19 +000047NACKStringBuilder::~NACKStringBuilder() {}
48
danilchap162abd32015-12-10 02:39:40 -080049void NACKStringBuilder::PushNACK(uint16_t nack) {
Erik Språng242e22b2015-05-11 10:17:43 +020050 if (count_ == 0) {
51 stream_ << nack;
52 } else if (nack == prevNack_ + 1) {
53 consecutive_ = true;
Erik Språng61be2a42015-04-27 13:32:52 +020054 } else {
Erik Språng242e22b2015-05-11 10:17:43 +020055 if (consecutive_) {
56 stream_ << "-" << prevNack_;
57 consecutive_ = false;
edjee@google.com79b02892013-04-04 19:43:34 +000058 }
Erik Språng242e22b2015-05-11 10:17:43 +020059 stream_ << "," << nack;
Erik Språng61be2a42015-04-27 13:32:52 +020060 }
Erik Språng242e22b2015-05-11 10:17:43 +020061 count_++;
62 prevNack_ = nack;
edjee@google.com79b02892013-04-04 19:43:34 +000063}
64
Erik Språng61be2a42015-04-27 13:32:52 +020065std::string NACKStringBuilder::GetResult() {
Erik Språng242e22b2015-05-11 10:17:43 +020066 if (consecutive_) {
67 stream_ << "-" << prevNack_;
68 consecutive_ = false;
Erik Språng61be2a42015-04-27 13:32:52 +020069 }
Erik Språng242e22b2015-05-11 10:17:43 +020070 return stream_.str();
edjee@google.com79b02892013-04-04 19:43:34 +000071}
72
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000073RTCPSender::FeedbackState::FeedbackState()
74 : send_payload_type(0),
75 frequency_hz(0),
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +000076 packets_sent(0),
77 media_bytes_sent(0),
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000078 send_bitrate(0),
79 last_rr_ntp_secs(0),
80 last_rr_ntp_frac(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000081 remote_sr(0),
Erik Språng61be2a42015-04-27 13:32:52 +020082 has_last_xr_rr(false),
danilchap162abd32015-12-10 02:39:40 -080083 module(nullptr) {}
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000084
danilchap2f7dea12016-01-13 02:03:04 -080085class PacketContainer : public rtcp::CompoundPacket,
Erik Språngf7c57762015-12-04 10:40:35 +010086 public rtcp::RtcpPacket::PacketReadyCallback {
87 public:
88 explicit PacketContainer(Transport* transport)
89 : transport_(transport), bytes_sent_(0) {}
90 virtual ~PacketContainer() {
91 for (RtcpPacket* packet : appended_packets_)
92 delete packet;
93 }
94
95 void OnPacketReady(uint8_t* data, size_t length) override {
96 if (transport_->SendRtcp(data, length))
97 bytes_sent_ += length;
98 }
99
100 size_t SendPackets() {
danilchap2f7dea12016-01-13 02:03:04 -0800101 rtcp::CompoundPacket::Build(this);
Erik Språngf7c57762015-12-04 10:40:35 +0100102 return bytes_sent_;
103 }
104
105 private:
106 Transport* transport_;
107 size_t bytes_sent_;
108};
109
110class RTCPSender::RtcpContext {
111 public:
Erik Språng242e22b2015-05-11 10:17:43 +0200112 RtcpContext(const FeedbackState& feedback_state,
113 int32_t nack_size,
114 const uint16_t* nack_list,
115 bool repeat,
116 uint64_t picture_id,
Erik Språngf7c57762015-12-04 10:40:35 +0100117 uint32_t ntp_sec,
118 uint32_t ntp_frac,
119 PacketContainer* container)
120 : feedback_state_(feedback_state),
121 nack_size_(nack_size),
122 nack_list_(nack_list),
123 repeat_(repeat),
124 picture_id_(picture_id),
125 ntp_sec_(ntp_sec),
126 ntp_frac_(ntp_frac),
127 container_(container) {}
Erik Språng242e22b2015-05-11 10:17:43 +0200128
Erik Språngf7c57762015-12-04 10:40:35 +0100129 virtual ~RtcpContext() {}
Erik Språng242e22b2015-05-11 10:17:43 +0200130
Erik Språngf7c57762015-12-04 10:40:35 +0100131 const FeedbackState& feedback_state_;
132 const int32_t nack_size_;
133 const uint16_t* nack_list_;
134 const bool repeat_;
135 const uint64_t picture_id_;
136 const uint32_t ntp_sec_;
137 const uint32_t ntp_frac_;
Erik Språng242e22b2015-05-11 10:17:43 +0200138
Erik Språngf7c57762015-12-04 10:40:35 +0100139 PacketContainer* const container_;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200140};
141
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000142RTCPSender::RTCPSender(
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000143 bool audio,
144 Clock* clock,
145 ReceiveStatistics* receive_statistics,
sprang86fd9ed2015-09-29 04:45:43 -0700146 RtcpPacketTypeCounterObserver* packet_type_counter_observer,
147 Transport* outgoing_transport)
Peter Boströmac547a62015-09-17 23:03:57 +0200148 : audio_(audio),
Erik Språng242e22b2015-05-11 10:17:43 +0200149 clock_(clock),
danilchap47a740b2015-12-15 00:30:07 -0800150 random_(clock_->TimeInMicroseconds()),
pbosda903ea2015-10-02 02:36:56 -0700151 method_(RtcpMode::kOff),
sprang86fd9ed2015-09-29 04:45:43 -0700152 transport_(outgoing_transport),
niklase@google.com470e71d2011-07-07 08:21:25 +0000153
Erik Språng242e22b2015-05-11 10:17:43 +0200154 critical_section_rtcp_sender_(
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000155 CriticalSectionWrapper::CreateCriticalSection()),
Erik Språng242e22b2015-05-11 10:17:43 +0200156 using_nack_(false),
157 sending_(false),
158 remb_enabled_(false),
Erik Språng242e22b2015-05-11 10:17:43 +0200159 next_time_to_send_rtcp_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000160 start_timestamp_(0),
161 last_rtp_timestamp_(0),
162 last_frame_capture_time_ms_(-1),
Erik Språng242e22b2015-05-11 10:17:43 +0200163 ssrc_(0),
164 remote_ssrc_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000165 receive_statistics_(receive_statistics),
niklase@google.com470e71d2011-07-07 08:21:25 +0000166
Erik Språng242e22b2015-05-11 10:17:43 +0200167 sequence_number_fir_(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000168
Erik Språng242e22b2015-05-11 10:17:43 +0200169 remb_bitrate_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000170
Erik Språng242e22b2015-05-11 10:17:43 +0200171 tmmbr_help_(),
172 tmmbr_send_(0),
173 packet_oh_send_(0),
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000174
Erik Språng242e22b2015-05-11 10:17:43 +0200175 app_sub_type_(0),
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200176 app_name_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200177 app_data_(nullptr),
178 app_length_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000179
Erik Språng242e22b2015-05-11 10:17:43 +0200180 xr_send_receiver_reference_time_enabled_(false),
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000181 packet_type_counter_observer_(packet_type_counter_observer) {
Erik Språng242e22b2015-05-11 10:17:43 +0200182 memset(last_send_report_, 0, sizeof(last_send_report_));
183 memset(last_rtcp_time_, 0, sizeof(last_rtcp_time_));
sprang86fd9ed2015-09-29 04:45:43 -0700184 RTC_DCHECK(transport_ != nullptr);
Erik Språng242e22b2015-05-11 10:17:43 +0200185
186 builders_[kRtcpSr] = &RTCPSender::BuildSR;
187 builders_[kRtcpRr] = &RTCPSender::BuildRR;
Erik Språng0ea42d32015-06-25 14:46:16 +0200188 builders_[kRtcpSdes] = &RTCPSender::BuildSDES;
Erik Språng242e22b2015-05-11 10:17:43 +0200189 builders_[kRtcpPli] = &RTCPSender::BuildPLI;
190 builders_[kRtcpFir] = &RTCPSender::BuildFIR;
191 builders_[kRtcpSli] = &RTCPSender::BuildSLI;
192 builders_[kRtcpRpsi] = &RTCPSender::BuildRPSI;
193 builders_[kRtcpRemb] = &RTCPSender::BuildREMB;
194 builders_[kRtcpBye] = &RTCPSender::BuildBYE;
195 builders_[kRtcpApp] = &RTCPSender::BuildAPP;
196 builders_[kRtcpTmmbr] = &RTCPSender::BuildTMMBR;
197 builders_[kRtcpTmmbn] = &RTCPSender::BuildTMMBN;
198 builders_[kRtcpNack] = &RTCPSender::BuildNACK;
199 builders_[kRtcpXrVoipMetric] = &RTCPSender::BuildVoIPMetric;
200 builders_[kRtcpXrReceiverReferenceTime] =
201 &RTCPSender::BuildReceiverReferenceTime;
202 builders_[kRtcpXrDlrrReportBlock] = &RTCPSender::BuildDlrr;
niklase@google.com470e71d2011-07-07 08:21:25 +0000203}
204
danilchap162abd32015-12-10 02:39:40 -0800205RTCPSender::~RTCPSender() {}
niklase@google.com470e71d2011-07-07 08:21:25 +0000206
pbosda903ea2015-10-02 02:36:56 -0700207RtcpMode RTCPSender::Status() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200208 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
209 return method_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000210}
211
pbosda903ea2015-10-02 02:36:56 -0700212void RTCPSender::SetRTCPStatus(RtcpMode method) {
Erik Språng242e22b2015-05-11 10:17:43 +0200213 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
214 method_ = method;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000215
pbosda903ea2015-10-02 02:36:56 -0700216 if (method == RtcpMode::kOff)
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000217 return;
Erik Språng242e22b2015-05-11 10:17:43 +0200218 next_time_to_send_rtcp_ =
219 clock_->TimeInMilliseconds() +
220 (audio_ ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000221}
222
Erik Språng61be2a42015-04-27 13:32:52 +0200223bool RTCPSender::Sending() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200224 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
225 return sending_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000226}
227
Erik Språng61be2a42015-04-27 13:32:52 +0200228int32_t RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
229 bool sending) {
230 bool sendRTCPBye = false;
231 {
Erik Språng242e22b2015-05-11 10:17:43 +0200232 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000233
pbosda903ea2015-10-02 02:36:56 -0700234 if (method_ != RtcpMode::kOff) {
Erik Språng242e22b2015-05-11 10:17:43 +0200235 if (sending == false && sending_ == true) {
Erik Språng61be2a42015-04-27 13:32:52 +0200236 // Trigger RTCP bye
237 sendRTCPBye = true;
238 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000239 }
Erik Språng242e22b2015-05-11 10:17:43 +0200240 sending_ = sending;
Erik Språng61be2a42015-04-27 13:32:52 +0200241 }
242 if (sendRTCPBye)
243 return SendRTCP(feedback_state, kRtcpBye);
244 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000245}
246
Erik Språng61be2a42015-04-27 13:32:52 +0200247bool RTCPSender::REMB() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200248 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
249 return remb_enabled_;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000250}
251
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000252void RTCPSender::SetREMBStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200253 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
254 remb_enabled_ = enable;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000255}
256
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000257void RTCPSender::SetREMBData(uint32_t bitrate,
258 const std::vector<uint32_t>& ssrcs) {
Erik Språng242e22b2015-05-11 10:17:43 +0200259 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
260 remb_bitrate_ = bitrate;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000261 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000262
Erik Språng242e22b2015-05-11 10:17:43 +0200263 if (remb_enabled_)
264 SetFlag(kRtcpRemb, false);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000265 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
266 // throttled by the caller.
Erik Språng242e22b2015-05-11 10:17:43 +0200267 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000268}
269
Erik Språng61be2a42015-04-27 13:32:52 +0200270bool RTCPSender::TMMBR() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200271 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
272 return IsFlagPresent(RTCPPacketType::kRtcpTmmbr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000273}
274
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000275void RTCPSender::SetTMMBRStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200276 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
277 if (enable) {
278 SetFlag(RTCPPacketType::kRtcpTmmbr, false);
279 } else {
280 ConsumeFlag(RTCPPacketType::kRtcpTmmbr, true);
281 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000282}
283
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000284void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
Erik Språng242e22b2015-05-11 10:17:43 +0200285 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000286 start_timestamp_ = start_timestamp;
287}
288
289void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
290 int64_t capture_time_ms) {
Erik Språng242e22b2015-05-11 10:17:43 +0200291 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000292 last_rtp_timestamp_ = rtp_timestamp;
293 if (capture_time_ms < 0) {
294 // We don't currently get a capture time from VoiceEngine.
Erik Språng242e22b2015-05-11 10:17:43 +0200295 last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000296 } else {
297 last_frame_capture_time_ms_ = capture_time_ms;
298 }
299}
300
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000301void RTCPSender::SetSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200302 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000303
Erik Språng242e22b2015-05-11 10:17:43 +0200304 if (ssrc_ != 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200305 // not first SetSSRC, probably due to a collision
306 // schedule a new RTCP report
307 // make sure that we send a RTP packet
Erik Språng242e22b2015-05-11 10:17:43 +0200308 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
Erik Språng61be2a42015-04-27 13:32:52 +0200309 }
Erik Språng242e22b2015-05-11 10:17:43 +0200310 ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000311}
312
Erik Språng61be2a42015-04-27 13:32:52 +0200313void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200314 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
315 remote_ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000316}
317
Peter Boström9ba52f82015-06-01 14:12:28 +0200318int32_t RTCPSender::SetCNAME(const char* c_name) {
319 if (!c_name)
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000320 return -1;
321
henrikg91d6ede2015-09-17 00:24:34 -0700322 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
Erik Språng242e22b2015-05-11 10:17:43 +0200323 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200324 cname_ = c_name;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000325 return 0;
326}
327
Erik Språng0ea42d32015-06-25 14:46:16 +0200328int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC, const char* c_name) {
329 assert(c_name);
henrikg91d6ede2015-09-17 00:24:34 -0700330 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
Erik Språng242e22b2015-05-11 10:17:43 +0200331 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200332 if (csrc_cnames_.size() >= kRtpCsrcSize)
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000333 return -1;
Erik Språng0ea42d32015-06-25 14:46:16 +0200334
335 csrc_cnames_[SSRC] = c_name;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000336 return 0;
337}
338
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000339int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
Erik Språng242e22b2015-05-11 10:17:43 +0200340 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200341 auto it = csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000342
Erik Språng242e22b2015-05-11 10:17:43 +0200343 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000344 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200345
Erik Språng242e22b2015-05-11 10:17:43 +0200346 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000347 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000348}
349
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000350bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
danilchap162abd32015-12-10 02:39:40 -0800351 /*
352 For audio we use a fix 5 sec interval
niklase@google.com470e71d2011-07-07 08:21:25 +0000353
danilchap162abd32015-12-10 02:39:40 -0800354 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
355 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
356 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000357
358
danilchap162abd32015-12-10 02:39:40 -0800359 From RFC 3550
niklase@google.com470e71d2011-07-07 08:21:25 +0000360
danilchap162abd32015-12-10 02:39:40 -0800361 MAX RTCP BW is 5% if the session BW
362 A send report is approximately 65 bytes inc CNAME
363 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000364
danilchap162abd32015-12-10 02:39:40 -0800365 The RECOMMENDED value for the reduced minimum in seconds is 360
366 divided by the session bandwidth in kilobits/second. This minimum
367 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
niklase@google.com470e71d2011-07-07 08:21:25 +0000368
danilchap162abd32015-12-10 02:39:40 -0800369 If the participant has not yet sent an RTCP packet (the variable
370 initial is true), the constant Tmin is set to 2.5 seconds, else it
371 is set to 5 seconds.
niklase@google.com470e71d2011-07-07 08:21:25 +0000372
danilchap162abd32015-12-10 02:39:40 -0800373 The interval between RTCP packets is varied randomly over the
374 range [0.5,1.5] times the calculated interval to avoid unintended
375 synchronization of all participants
niklase@google.com470e71d2011-07-07 08:21:25 +0000376
danilchap162abd32015-12-10 02:39:40 -0800377 if we send
378 If the participant is a sender (we_sent true), the constant C is
379 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
380 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
381 number of senders.
niklase@google.com470e71d2011-07-07 08:21:25 +0000382
danilchap162abd32015-12-10 02:39:40 -0800383 if we receive only
384 If we_sent is not true, the constant C is set
385 to the average RTCP packet size divided by 75% of the RTCP
386 bandwidth. The constant n is set to the number of receivers
387 (members - senders). If the number of senders is greater than
388 25%, senders and receivers are treated together.
niklase@google.com470e71d2011-07-07 08:21:25 +0000389
danilchap162abd32015-12-10 02:39:40 -0800390 reconsideration NOT required for peer-to-peer
391 "timer reconsideration" is
392 employed. This algorithm implements a simple back-off mechanism
393 which causes users to hold back RTCP packet transmission if the
394 group sizes are increasing.
niklase@google.com470e71d2011-07-07 08:21:25 +0000395
danilchap162abd32015-12-10 02:39:40 -0800396 n = number of members
397 C = avg_size/(rtcpBW/4)
niklase@google.com470e71d2011-07-07 08:21:25 +0000398
danilchap162abd32015-12-10 02:39:40 -0800399 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
niklase@google.com470e71d2011-07-07 08:21:25 +0000400
danilchap162abd32015-12-10 02:39:40 -0800401 4. The calculated interval T is set to a number uniformly distributed
402 between 0.5 and 1.5 times the deterministic calculated interval.
niklase@google.com470e71d2011-07-07 08:21:25 +0000403
danilchap162abd32015-12-10 02:39:40 -0800404 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
405 for the fact that the timer reconsideration algorithm converges to
406 a value of the RTCP bandwidth below the intended average
407 */
niklase@google.com470e71d2011-07-07 08:21:25 +0000408
Erik Språng242e22b2015-05-11 10:17:43 +0200409 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000410
Erik Språng242e22b2015-05-11 10:17:43 +0200411 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
xians@webrtc.org8738d272011-11-25 13:43:53 +0000412
pbosda903ea2015-10-02 02:36:56 -0700413 if (method_ == RtcpMode::kOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000414 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000415
Erik Språng242e22b2015-05-11 10:17:43 +0200416 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200417 // for video key-frames we want to send the RTCP before the large key-frame
418 // if we have a 100 ms margin
419 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
420 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000421
Erik Språng242e22b2015-05-11 10:17:43 +0200422 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200423 return true;
424 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200425 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200426 // wrap
427 return true;
428 }
429 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000430}
431
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000432int64_t RTCPSender::SendTimeOfSendReport(uint32_t sendReport) {
Erik Språng242e22b2015-05-11 10:17:43 +0200433 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000434
Erik Språng61be2a42015-04-27 13:32:52 +0200435 // This is only saved when we are the sender
Erik Språng242e22b2015-05-11 10:17:43 +0200436 if ((last_send_report_[0] == 0) || (sendReport == 0)) {
Erik Språng61be2a42015-04-27 13:32:52 +0200437 return 0; // will be ignored
438 } else {
439 for (int i = 0; i < RTCP_NUMBER_OF_SR; ++i) {
Erik Språng242e22b2015-05-11 10:17:43 +0200440 if (last_send_report_[i] == sendReport)
441 return last_rtcp_time_[i];
niklase@google.com470e71d2011-07-07 08:21:25 +0000442 }
Erik Språng61be2a42015-04-27 13:32:52 +0200443 }
444 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000445}
446
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000447bool RTCPSender::SendTimeOfXrRrReport(uint32_t mid_ntp,
448 int64_t* time_ms) const {
Erik Språng242e22b2015-05-11 10:17:43 +0200449 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000450
451 if (last_xr_rr_.empty()) {
452 return false;
453 }
454 std::map<uint32_t, int64_t>::const_iterator it = last_xr_rr_.find(mid_ntp);
455 if (it == last_xr_rr_.end()) {
456 return false;
457 }
458 *time_ms = it->second;
459 return true;
460}
461
Erik Språngf7c57762015-12-04 10:40:35 +0100462rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildSR(const RtcpContext& ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200463 for (int i = (RTCP_NUMBER_OF_SR - 2); i >= 0; i--) {
464 // shift old
Erik Språng242e22b2015-05-11 10:17:43 +0200465 last_send_report_[i + 1] = last_send_report_[i];
466 last_rtcp_time_[i + 1] = last_rtcp_time_[i];
Erik Språng61be2a42015-04-27 13:32:52 +0200467 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000468
Erik Språngf7c57762015-12-04 10:40:35 +0100469 last_rtcp_time_[0] = Clock::NtpToMs(ctx.ntp_sec_, ctx.ntp_frac_);
470 last_send_report_[0] = (ctx.ntp_sec_ << 16) + (ctx.ntp_frac_ >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000471
Erik Språng61be2a42015-04-27 13:32:52 +0200472 // The timestamp of this RTCP packet should be estimated as the timestamp of
473 // the frame being captured at this moment. We are calculating that
474 // timestamp as the last frame's timestamp + the time since the last frame
475 // was captured.
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200476 uint32_t rtp_timestamp =
477 start_timestamp_ + last_rtp_timestamp_ +
478 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) *
Erik Språngf7c57762015-12-04 10:40:35 +0100479 (ctx.feedback_state_.frequency_hz / 1000);
niklase@google.com470e71d2011-07-07 08:21:25 +0000480
Erik Språngf7c57762015-12-04 10:40:35 +0100481 rtcp::SenderReport* report = new rtcp::SenderReport();
482 report->From(ssrc_);
483 report->WithNtpSec(ctx.ntp_sec_);
484 report->WithNtpFrac(ctx.ntp_frac_);
485 report->WithRtpTimestamp(rtp_timestamp);
486 report->WithPacketCount(ctx.feedback_state_.packets_sent);
487 report->WithOctetCount(ctx.feedback_state_.media_bytes_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000488
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200489 for (auto it : report_blocks_)
Erik Språngf7c57762015-12-04 10:40:35 +0100490 report->WithReportBlock(it.second);
niklase@google.com470e71d2011-07-07 08:21:25 +0000491
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200492 report_blocks_.clear();
Erik Språngf7c57762015-12-04 10:40:35 +0100493
494 return rtc::scoped_ptr<rtcp::SenderReport>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000495}
496
Erik Språngf7c57762015-12-04 10:40:35 +0100497rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildSDES(
498 const RtcpContext& ctx) {
Erik Språng0ea42d32015-06-25 14:46:16 +0200499 size_t length_cname = cname_.length();
henrikg91d6ede2015-09-17 00:24:34 -0700500 RTC_CHECK_LT(length_cname, static_cast<size_t>(RTCP_CNAME_SIZE));
niklase@google.com470e71d2011-07-07 08:21:25 +0000501
Erik Språngf7c57762015-12-04 10:40:35 +0100502 rtcp::Sdes* sdes = new rtcp::Sdes();
503 sdes->WithCName(ssrc_, cname_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200504
505 for (const auto it : csrc_cnames_)
Erik Språngf7c57762015-12-04 10:40:35 +0100506 sdes->WithCName(it.first, it.second);
Erik Språng0ea42d32015-06-25 14:46:16 +0200507
Erik Språngf7c57762015-12-04 10:40:35 +0100508 return rtc::scoped_ptr<rtcp::Sdes>(sdes);
niklase@google.com470e71d2011-07-07 08:21:25 +0000509}
510
Erik Språngf7c57762015-12-04 10:40:35 +0100511rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildRR(const RtcpContext& ctx) {
512 rtcp::ReceiverReport* report = new rtcp::ReceiverReport();
513 report->From(ssrc_);
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200514 for (auto it : report_blocks_)
Erik Språngf7c57762015-12-04 10:40:35 +0100515 report->WithReportBlock(it.second);
Erik Språng61be2a42015-04-27 13:32:52 +0200516
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200517 report_blocks_.clear();
Erik Språngf7c57762015-12-04 10:40:35 +0100518 return rtc::scoped_ptr<rtcp::ReceiverReport>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000519}
520
Erik Språngf7c57762015-12-04 10:40:35 +0100521rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildPLI(const RtcpContext& ctx) {
522 rtcp::Pli* pli = new rtcp::Pli();
523 pli->From(ssrc_);
524 pli->To(remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200525
Erik Språng242e22b2015-05-11 10:17:43 +0200526 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
527 "RTCPSender::PLI");
528 ++packet_type_counter_.pli_packets;
529 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
530 ssrc_, packet_type_counter_.pli_packets);
531
Erik Språngf7c57762015-12-04 10:40:35 +0100532 return rtc::scoped_ptr<rtcp::Pli>(pli);
Erik Språng61be2a42015-04-27 13:32:52 +0200533}
534
Erik Språngf7c57762015-12-04 10:40:35 +0100535rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildFIR(const RtcpContext& ctx) {
536 if (!ctx.repeat_)
sprang62dae192015-08-05 02:35:35 -0700537 ++sequence_number_fir_; // Do not increase if repetition.
niklase@google.com470e71d2011-07-07 08:21:25 +0000538
Erik Språngf7c57762015-12-04 10:40:35 +0100539 rtcp::Fir* fir = new rtcp::Fir();
540 fir->From(ssrc_);
541 fir->To(remote_ssrc_);
542 fir->WithCommandSeqNum(sequence_number_fir_);
Erik Språng242e22b2015-05-11 10:17:43 +0200543
544 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
545 "RTCPSender::FIR");
546 ++packet_type_counter_.fir_packets;
547 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
548 ssrc_, packet_type_counter_.fir_packets);
549
Erik Språngf7c57762015-12-04 10:40:35 +0100550 return rtc::scoped_ptr<rtcp::Fir>(fir);
niklase@google.com470e71d2011-07-07 08:21:25 +0000551}
552
553/*
554 0 1 2 3
555 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
556 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
557 | First | Number | PictureID |
558 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
559*/
Erik Språngf7c57762015-12-04 10:40:35 +0100560rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildSLI(const RtcpContext& ctx) {
561 rtcp::Sli* sli = new rtcp::Sli();
562 sli->From(ssrc_);
563 sli->To(remote_ssrc_);
sprang0365a272015-08-11 01:02:37 -0700564 // Crop picture id to 6 least significant bits.
Erik Språngf7c57762015-12-04 10:40:35 +0100565 sli->WithPictureId(ctx.picture_id_ & 0x3F);
sprang0365a272015-08-11 01:02:37 -0700566
Erik Språngf7c57762015-12-04 10:40:35 +0100567 return rtc::scoped_ptr<rtcp::Sli>(sli);
niklase@google.com470e71d2011-07-07 08:21:25 +0000568}
569
570/*
571 0 1 2 3
572 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
573 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
574 | PB |0| Payload Type| Native RPSI bit string |
575 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
576 | defined per codec ... | Padding (0) |
577 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
578*/
579/*
580* Note: not generic made for VP8
581*/
Erik Språngf7c57762015-12-04 10:40:35 +0100582rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildRPSI(
583 const RtcpContext& ctx) {
584 if (ctx.feedback_state_.send_payload_type == 0xFF)
585 return nullptr;
Erik Språng242e22b2015-05-11 10:17:43 +0200586
Erik Språngf7c57762015-12-04 10:40:35 +0100587 rtcp::Rpsi* rpsi = new rtcp::Rpsi();
588 rpsi->From(ssrc_);
589 rpsi->To(remote_ssrc_);
590 rpsi->WithPayloadType(ctx.feedback_state_.send_payload_type);
591 rpsi->WithPictureId(ctx.picture_id_);
sprangcf7f54d2015-08-13 04:37:42 -0700592
Erik Språngf7c57762015-12-04 10:40:35 +0100593 return rtc::scoped_ptr<rtcp::Rpsi>(rpsi);
niklase@google.com470e71d2011-07-07 08:21:25 +0000594}
595
Erik Språngf7c57762015-12-04 10:40:35 +0100596rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildREMB(
597 const RtcpContext& ctx) {
598 rtcp::Remb* remb = new rtcp::Remb();
599 remb->From(ssrc_);
sprangdd4edc52015-08-21 04:21:51 -0700600 for (uint32_t ssrc : remb_ssrcs_)
Erik Språngf7c57762015-12-04 10:40:35 +0100601 remb->AppliesTo(ssrc);
602 remb->WithBitrateBps(remb_bitrate_);
Erik Språng61be2a42015-04-27 13:32:52 +0200603
Erik Språng242e22b2015-05-11 10:17:43 +0200604 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
605 "RTCPSender::REMB");
606
Erik Språngf7c57762015-12-04 10:40:35 +0100607 return rtc::scoped_ptr<rtcp::Remb>(remb);
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000608}
609
Erik Språng61be2a42015-04-27 13:32:52 +0200610void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
Erik Språng242e22b2015-05-11 10:17:43 +0200611 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
612 tmmbr_send_ = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000613}
614
Erik Språngf7c57762015-12-04 10:40:35 +0100615rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBR(
616 const RtcpContext& ctx) {
617 if (ctx.feedback_state_.module == nullptr)
618 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200619 // Before sending the TMMBR check the received TMMBN, only an owner is
620 // allowed to raise the bitrate:
621 // * If the sender is an owner of the TMMBN -> send TMMBR
622 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000623
Erik Språng61be2a42015-04-27 13:32:52 +0200624 // get current bounding set from RTCP receiver
625 bool tmmbrOwner = false;
626 // store in candidateSet, allocates one extra slot
Erik Språng242e22b2015-05-11 10:17:43 +0200627 TMMBRSet* candidateSet = tmmbr_help_.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000628
Erik Språng242e22b2015-05-11 10:17:43 +0200629 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
630 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
Erik Språng61be2a42015-04-27 13:32:52 +0200631 // since RTCPreceiver is not doing the reverse we should be fine
632 int32_t lengthOfBoundingSet =
danilchap6db6cdc2015-12-15 02:54:47 -0800633 ctx.feedback_state_.module->BoundingSet(&tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +0000634
Erik Språng61be2a42015-04-27 13:32:52 +0200635 if (lengthOfBoundingSet > 0) {
636 for (int32_t i = 0; i < lengthOfBoundingSet; i++) {
Erik Språng242e22b2015-05-11 10:17:43 +0200637 if (candidateSet->Tmmbr(i) == tmmbr_send_ &&
638 candidateSet->PacketOH(i) == packet_oh_send_) {
Erik Språngf7c57762015-12-04 10:40:35 +0100639 // Do not send the same tuple.
640 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200641 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000642 }
Erik Språng61be2a42015-04-27 13:32:52 +0200643 if (!tmmbrOwner) {
644 // use received bounding set as candidate set
645 // add current tuple
Erik Språng242e22b2015-05-11 10:17:43 +0200646 candidateSet->SetEntry(lengthOfBoundingSet, tmmbr_send_, packet_oh_send_,
647 ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200648 int numCandidates = lengthOfBoundingSet + 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000649
Erik Språng61be2a42015-04-27 13:32:52 +0200650 // find bounding set
Erik Språngf7c57762015-12-04 10:40:35 +0100651 TMMBRSet* boundingSet = nullptr;
Erik Språng242e22b2015-05-11 10:17:43 +0200652 int numBoundingSet = tmmbr_help_.FindTMMBRBoundingSet(boundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200653 if (numBoundingSet > 0 || numBoundingSet <= numCandidates)
Erik Språng242e22b2015-05-11 10:17:43 +0200654 tmmbrOwner = tmmbr_help_.IsOwner(ssrc_, numBoundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200655 if (!tmmbrOwner) {
Erik Språngf7c57762015-12-04 10:40:35 +0100656 // Did not enter bounding set, no meaning to send this request.
657 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200658 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000659 }
Erik Språng61be2a42015-04-27 13:32:52 +0200660 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000661
Erik Språngf7c57762015-12-04 10:40:35 +0100662 if (!tmmbr_send_)
663 return nullptr;
sprang81a3e602015-08-21 05:30:11 -0700664
Erik Språngf7c57762015-12-04 10:40:35 +0100665 rtcp::Tmmbr* tmmbr = new rtcp::Tmmbr();
666 tmmbr->From(ssrc_);
667 tmmbr->To(remote_ssrc_);
668 tmmbr->WithBitrateKbps(tmmbr_send_);
669 tmmbr->WithOverhead(packet_oh_send_);
670
671 return rtc::scoped_ptr<rtcp::Tmmbr>(tmmbr);
Erik Språng61be2a42015-04-27 13:32:52 +0200672}
673
Erik Språngf7c57762015-12-04 10:40:35 +0100674rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBN(
675 const RtcpContext& ctx) {
Erik Språng242e22b2015-05-11 10:17:43 +0200676 TMMBRSet* boundingSet = tmmbr_help_.BoundingSetToSend();
Erik Språngf7c57762015-12-04 10:40:35 +0100677 if (boundingSet == nullptr)
678 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200679
Erik Språngf7c57762015-12-04 10:40:35 +0100680 rtcp::Tmmbn* tmmbn = new rtcp::Tmmbn();
681 tmmbn->From(ssrc_);
sprangd83df502015-08-27 01:05:08 -0700682 for (uint32_t i = 0; i < boundingSet->lengthOfSet(); i++) {
683 if (boundingSet->Tmmbr(i) > 0) {
Erik Språngf7c57762015-12-04 10:40:35 +0100684 tmmbn->WithTmmbr(boundingSet->Ssrc(i), boundingSet->Tmmbr(i),
685 boundingSet->PacketOH(i));
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000686 }
Erik Språng61be2a42015-04-27 13:32:52 +0200687 }
sprangd83df502015-08-27 01:05:08 -0700688
Erik Språngf7c57762015-12-04 10:40:35 +0100689 return rtc::scoped_ptr<rtcp::Tmmbn>(tmmbn);
niklase@google.com470e71d2011-07-07 08:21:25 +0000690}
691
Erik Språngf7c57762015-12-04 10:40:35 +0100692rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildAPP(const RtcpContext& ctx) {
693 rtcp::App* app = new rtcp::App();
694 app->From(ssrc_);
695 app->WithSubType(app_sub_type_);
696 app->WithName(app_name_);
697 app->WithData(app_data_.get(), app_length_);
Erik Språng521875a2015-09-01 10:11:16 +0200698
Erik Språngf7c57762015-12-04 10:40:35 +0100699 return rtc::scoped_ptr<rtcp::App>(app);
Erik Språng61be2a42015-04-27 13:32:52 +0200700}
701
Erik Språngf7c57762015-12-04 10:40:35 +0100702rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildNACK(
703 const RtcpContext& ctx) {
704 rtcp::Nack* nack = new rtcp::Nack();
705 nack->From(ssrc_);
706 nack->To(remote_ssrc_);
707 nack->WithList(ctx.nack_list_, ctx.nack_size_);
Erik Språng61be2a42015-04-27 13:32:52 +0200708
709 // Report stats.
710 NACKStringBuilder stringBuilder;
Erik Språngf7c57762015-12-04 10:40:35 +0100711 for (int idx = 0; idx < ctx.nack_size_; ++idx) {
712 stringBuilder.PushNACK(ctx.nack_list_[idx]);
713 nack_stats_.ReportRequest(ctx.nack_list_[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +0200714 }
Erik Språng61be2a42015-04-27 13:32:52 +0200715 packet_type_counter_.nack_requests = nack_stats_.requests();
716 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +0200717
718 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
719 "RTCPSender::NACK", "nacks",
720 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
721 ++packet_type_counter_.nack_packets;
722 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
723 ssrc_, packet_type_counter_.nack_packets);
724
Erik Språngf7c57762015-12-04 10:40:35 +0100725 return rtc::scoped_ptr<rtcp::Nack>(nack);
Erik Språng61be2a42015-04-27 13:32:52 +0200726}
727
Erik Språngf7c57762015-12-04 10:40:35 +0100728rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildBYE(const RtcpContext& ctx) {
729 rtcp::Bye* bye = new rtcp::Bye();
730 bye->From(ssrc_);
sprangd8ee4f92015-08-24 03:25:19 -0700731 for (uint32_t csrc : csrcs_)
Erik Språngf7c57762015-12-04 10:40:35 +0100732 bye->WithCsrc(csrc);
sprangd8ee4f92015-08-24 03:25:19 -0700733
Erik Språngf7c57762015-12-04 10:40:35 +0100734 return rtc::scoped_ptr<rtcp::Bye>(bye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000735}
736
Erik Språngf7c57762015-12-04 10:40:35 +0100737rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildReceiverReferenceTime(
738 const RtcpContext& ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200739 if (last_xr_rr_.size() >= RTCP_NUMBER_OF_SR)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000740 last_xr_rr_.erase(last_xr_rr_.begin());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000741 last_xr_rr_.insert(std::pair<uint32_t, int64_t>(
Erik Språngf7c57762015-12-04 10:40:35 +0100742 RTCPUtility::MidNtp(ctx.ntp_sec_, ctx.ntp_frac_),
743 Clock::NtpToMs(ctx.ntp_sec_, ctx.ntp_frac_)));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000744
Erik Språngf7c57762015-12-04 10:40:35 +0100745 rtcp::Xr* xr = new rtcp::Xr();
746 xr->From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000747
Erik Språngca28fdc2015-08-31 14:00:50 +0200748 rtcp::Rrtr rrtr;
Danil Chapovalovfc47ed62015-12-07 14:46:35 +0100749 rrtr.WithNtp(NtpTime(ctx.ntp_sec_, ctx.ntp_frac_));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000750
Erik Språngf7c57762015-12-04 10:40:35 +0100751 xr->WithRrtr(&rrtr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000752
Erik Språngca28fdc2015-08-31 14:00:50 +0200753 // TODO(sprang): Merge XR report sending to contain all of RRTR, DLRR, VOIP?
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000754
Erik Språngf7c57762015-12-04 10:40:35 +0100755 return rtc::scoped_ptr<rtcp::Xr>(xr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000756}
757
Erik Språngf7c57762015-12-04 10:40:35 +0100758rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildDlrr(
759 const RtcpContext& ctx) {
760 rtcp::Xr* xr = new rtcp::Xr();
761 xr->From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000762
Erik Språngca28fdc2015-08-31 14:00:50 +0200763 rtcp::Dlrr dlrr;
Erik Språngf7c57762015-12-04 10:40:35 +0100764 const RtcpReceiveTimeInfo& info = ctx.feedback_state_.last_xr_rr;
Erik Språngca28fdc2015-08-31 14:00:50 +0200765 dlrr.WithDlrrItem(info.sourceSSRC, info.lastRR, info.delaySinceLastRR);
766
Erik Språngf7c57762015-12-04 10:40:35 +0100767 xr->WithDlrr(&dlrr);
Erik Språngca28fdc2015-08-31 14:00:50 +0200768
Erik Språngf7c57762015-12-04 10:40:35 +0100769 return rtc::scoped_ptr<rtcp::Xr>(xr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000770}
771
Erik Språng242e22b2015-05-11 10:17:43 +0200772// TODO(sprang): Add a unit test for this, or remove if the code isn't used.
Erik Språngf7c57762015-12-04 10:40:35 +0100773rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildVoIPMetric(
774 const RtcpContext& context) {
775 rtcp::Xr* xr = new rtcp::Xr();
776 xr->From(ssrc_);
Erik Språngca28fdc2015-08-31 14:00:50 +0200777
778 rtcp::VoipMetric voip;
779 voip.To(remote_ssrc_);
danilchap91941ae2015-12-15 07:06:36 -0800780 voip.WithVoipMetric(xr_voip_metric_);
Erik Språngca28fdc2015-08-31 14:00:50 +0200781
Erik Språngf7c57762015-12-04 10:40:35 +0100782 xr->WithVoipMetric(&voip);
Erik Språngca28fdc2015-08-31 14:00:50 +0200783
Erik Språngf7c57762015-12-04 10:40:35 +0100784 return rtc::scoped_ptr<rtcp::Xr>(xr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000785}
786
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000787int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200788 RTCPPacketType packetType,
789 int32_t nack_size,
790 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000791 bool repeat,
792 uint64_t pictureID) {
Erik Språng242e22b2015-05-11 10:17:43 +0200793 return SendCompoundRTCP(
794 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
795 nack_size, nack_list, repeat, pictureID);
796}
797
798int32_t RTCPSender::SendCompoundRTCP(
799 const FeedbackState& feedback_state,
Erik Språngf7c57762015-12-04 10:40:35 +0100800 const std::set<RTCPPacketType>& packet_types,
Erik Språng242e22b2015-05-11 10:17:43 +0200801 int32_t nack_size,
802 const uint16_t* nack_list,
803 bool repeat,
804 uint64_t pictureID) {
Erik Språngf7c57762015-12-04 10:40:35 +0100805 PacketContainer container(transport_);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000806 {
Erik Språng242e22b2015-05-11 10:17:43 +0200807 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
pbosda903ea2015-10-02 02:36:56 -0700808 if (method_ == RtcpMode::kOff) {
Erik Språng61be2a42015-04-27 13:32:52 +0200809 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
810 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +0000811 }
Erik Språngf7c57762015-12-04 10:40:35 +0100812
813 // We need to send our NTP even if we haven't received any reports.
814 uint32_t ntp_sec;
815 uint32_t ntp_frac;
816 clock_->CurrentNtp(ntp_sec, ntp_frac);
817 RtcpContext context(feedback_state, nack_size, nack_list, repeat, pictureID,
818 ntp_sec, ntp_frac, &container);
819
820 PrepareReport(packet_types, feedback_state);
821
822 auto it = report_flags_.begin();
823 while (it != report_flags_.end()) {
824 auto builder_it = builders_.find(it->type);
825 RTC_DCHECK(builder_it != builders_.end());
826 if (it->is_volatile) {
827 report_flags_.erase(it++);
828 } else {
829 ++it;
830 }
831
832 BuilderFunc func = builder_it->second;
833 rtc::scoped_ptr<rtcp::RtcpPacket> packet = (this->*func)(context);
834 if (packet.get() == nullptr)
835 return -1;
836 container.Append(packet.release());
837 }
838
839 if (packet_type_counter_observer_ != nullptr) {
840 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
841 remote_ssrc_, packet_type_counter_);
842 }
843
844 RTC_DCHECK(AllVolatileFlagsConsumed());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000845 }
Erik Språng61be2a42015-04-27 13:32:52 +0200846
Erik Språngf7c57762015-12-04 10:40:35 +0100847 size_t bytes_sent = container.SendPackets();
848 return bytes_sent == 0 ? -1 : 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000849}
850
Erik Språngf7c57762015-12-04 10:40:35 +0100851void RTCPSender::PrepareReport(const std::set<RTCPPacketType>& packetTypes,
852 const FeedbackState& feedback_state) {
Erik Språng242e22b2015-05-11 10:17:43 +0200853 // Add all flags as volatile. Non volatile entries will not be overwritten
854 // and all new volatile flags added will be consumed by the end of this call.
855 SetFlags(packetTypes, true);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000856
Erik Språng61be2a42015-04-27 13:32:52 +0200857 if (packet_type_counter_.first_packet_time_ms == -1)
Erik Språng242e22b2015-05-11 10:17:43 +0200858 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språng61be2a42015-04-27 13:32:52 +0200859
Erik Språng242e22b2015-05-11 10:17:43 +0200860 bool generate_report;
861 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
862 // Report type already explicitly set, don't automatically populate.
863 generate_report = true;
henrikg91d6ede2015-09-17 00:24:34 -0700864 RTC_DCHECK(ConsumeFlag(kRtcpReport) == false);
Erik Språng242e22b2015-05-11 10:17:43 +0200865 } else {
866 generate_report =
pbosda903ea2015-10-02 02:36:56 -0700867 (ConsumeFlag(kRtcpReport) && method_ == RtcpMode::kReducedSize) ||
868 method_ == RtcpMode::kCompound;
Erik Språng242e22b2015-05-11 10:17:43 +0200869 if (generate_report)
870 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000871 }
872
Erik Språng0ea42d32015-06-25 14:46:16 +0200873 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
Erik Språng242e22b2015-05-11 10:17:43 +0200874 SetFlag(kRtcpSdes, true);
875
Erik Språng242e22b2015-05-11 10:17:43 +0200876 if (generate_report) {
877 if (!sending_ && xr_send_receiver_reference_time_enabled_)
878 SetFlag(kRtcpXrReceiverReferenceTime, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200879 if (feedback_state.has_last_xr_rr)
Erik Språng242e22b2015-05-11 10:17:43 +0200880 SetFlag(kRtcpXrDlrrReportBlock, true);
881
882 // generate next time to send an RTCP report
danilchap47a740b2015-12-15 00:30:07 -0800883 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000884
danilchap47a740b2015-12-15 00:30:07 -0800885 if (!audio_) {
Erik Språng242e22b2015-05-11 10:17:43 +0200886 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200887 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
888 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
889 if (send_bitrate_kbit != 0)
890 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000891 }
Erik Språng61be2a42015-04-27 13:32:52 +0200892 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
893 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
Erik Språng61be2a42015-04-27 13:32:52 +0200894 }
danilchap47a740b2015-12-15 00:30:07 -0800895 // The interval between RTCP packets is varied randomly over the
896 // range [1/2,3/2] times the calculated interval.
897 uint32_t timeToNext =
898 random_.Rand(minIntervalMs * 1 / 2, minIntervalMs * 3 / 2);
Erik Språng242e22b2015-05-11 10:17:43 +0200899 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000900
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000901 StatisticianMap statisticians =
902 receive_statistics_->GetActiveStatisticians();
danilchapa72e7342015-12-22 08:07:45 -0800903 RTC_DCHECK(report_blocks_.empty());
904 for (auto& it : statisticians) {
905 AddReportBlock(feedback_state, it.first, it.second);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000906 }
907 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000908}
909
danilchapa72e7342015-12-22 08:07:45 -0800910bool RTCPSender::AddReportBlock(const FeedbackState& feedback_state,
911 uint32_t ssrc,
912 StreamStatistician* statistician) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000913 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000914 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000915 if (!statistician->GetStatistics(&stats, true))
916 return false;
danilchapa72e7342015-12-22 08:07:45 -0800917
918 if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) {
919 LOG(LS_WARNING) << "Too many report blocks.";
920 return false;
921 }
922 RTC_DCHECK(report_blocks_.find(ssrc) == report_blocks_.end());
923 rtcp::ReportBlock* block = &report_blocks_[ssrc];
924 block->To(ssrc);
925 block->WithFractionLost(stats.fraction_lost);
926 if (!block->WithCumulativeLost(stats.cumulative_lost)) {
927 report_blocks_.erase(ssrc);
928 LOG(LS_WARNING) << "Cumulative lost is oversized.";
929 return false;
930 }
931 block->WithExtHighestSeqNum(stats.extended_max_sequence_number);
932 block->WithJitter(stats.jitter);
933 block->WithLastSr(feedback_state.remote_sr);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000934
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200935 // TODO(sprang): Do we really need separate time stamps for each report?
936 // Get our NTP as late as possible to avoid a race.
937 uint32_t ntp_secs;
938 uint32_t ntp_frac;
939 clock_->CurrentNtp(ntp_secs, ntp_frac);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000940
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200941 // Delay since last received report.
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000942 if ((feedback_state.last_rr_ntp_secs != 0) ||
943 (feedback_state.last_rr_ntp_frac != 0)) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200944 // Get the 16 lowest bits of seconds and the 16 highest bits of fractions.
945 uint32_t now = ntp_secs & 0x0000FFFF;
Erik Språng61be2a42015-04-27 13:32:52 +0200946 now <<= 16;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200947 now += (ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000948
Erik Språng61be2a42015-04-27 13:32:52 +0200949 uint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
950 receiveTime <<= 16;
951 receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000952
danilchapa72e7342015-12-22 08:07:45 -0800953 block->WithDelayLastSr(now - receiveTime);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000954 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000955 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000956}
957
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000958void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
959 assert(csrcs.size() <= kRtpCsrcSize);
Erik Språng242e22b2015-05-11 10:17:43 +0200960 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000961 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +0000962}
963
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000964int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
965 uint32_t name,
966 const uint8_t* data,
967 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +0200968 if (length % 4 != 0) {
969 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
970 return -1;
971 }
Erik Språng242e22b2015-05-11 10:17:43 +0200972 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000973
Erik Språng242e22b2015-05-11 10:17:43 +0200974 SetFlag(kRtcpApp, true);
975 app_sub_type_ = subType;
976 app_name_ = name;
977 app_data_.reset(new uint8_t[length]);
978 app_length_ = length;
979 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +0200980 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000981}
982
Erik Språng61be2a42015-04-27 13:32:52 +0200983int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
Erik Språng242e22b2015-05-11 10:17:43 +0200984 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
985 memcpy(&xr_voip_metric_, VoIPMetric, sizeof(RTCPVoIPMetric));
niklase@google.com470e71d2011-07-07 08:21:25 +0000986
Erik Språng242e22b2015-05-11 10:17:43 +0200987 SetFlag(kRtcpXrVoipMetric, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200988 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000989}
990
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000991void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200992 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
993 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000994}
995
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000996bool RTCPSender::RtcpXrReceiverReferenceTime() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200997 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
998 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000999}
1000
niklase@google.com470e71d2011-07-07 08:21:25 +00001001// no callbacks allowed inside this function
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001002int32_t RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
1003 uint32_t maxBitrateKbit) {
Erik Språng242e22b2015-05-11 10:17:43 +02001004 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +00001005
Erik Språng242e22b2015-05-11 10:17:43 +02001006 if (0 == tmmbr_help_.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit)) {
1007 SetFlag(kRtcpTmmbn, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001008 return 0;
1009 }
1010 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001011}
Erik Språng61be2a42015-04-27 13:32:52 +02001012
Erik Språng242e22b2015-05-11 10:17:43 +02001013void RTCPSender::SetFlag(RTCPPacketType type, bool is_volatile) {
1014 report_flags_.insert(ReportFlag(type, is_volatile));
1015}
1016
1017void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
1018 bool is_volatile) {
1019 for (RTCPPacketType type : types)
1020 SetFlag(type, is_volatile);
1021}
1022
1023bool RTCPSender::IsFlagPresent(RTCPPacketType type) const {
1024 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
1025}
1026
1027bool RTCPSender::ConsumeFlag(RTCPPacketType type, bool forced) {
1028 auto it = report_flags_.find(ReportFlag(type, false));
1029 if (it == report_flags_.end())
1030 return false;
1031 if (it->is_volatile || forced)
1032 report_flags_.erase((it));
1033 return true;
1034}
1035
1036bool RTCPSender::AllVolatileFlagsConsumed() const {
1037 for (const ReportFlag& flag : report_flags_) {
1038 if (flag.is_volatile)
1039 return false;
1040 }
1041 return true;
1042}
1043
sprang233bd872015-09-08 13:25:16 -07001044bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
sprang233bd872015-09-08 13:25:16 -07001045 class Sender : public rtcp::RtcpPacket::PacketReadyCallback {
1046 public:
danilchap6db6cdc2015-12-15 02:54:47 -08001047 explicit Sender(Transport* transport)
Peter Boströmac547a62015-09-17 23:03:57 +02001048 : transport_(transport), send_failure_(false) {}
sprang233bd872015-09-08 13:25:16 -07001049
1050 void OnPacketReady(uint8_t* data, size_t length) override {
pbos2d566682015-09-28 09:59:31 -07001051 if (!transport_->SendRtcp(data, length))
sprang233bd872015-09-08 13:25:16 -07001052 send_failure_ = true;
1053 }
1054
1055 Transport* const transport_;
sprang233bd872015-09-08 13:25:16 -07001056 bool send_failure_;
sprang86fd9ed2015-09-29 04:45:43 -07001057 } sender(transport_);
sprang233bd872015-09-08 13:25:16 -07001058
1059 uint8_t buffer[IP_PACKET_SIZE];
1060 return packet.BuildExternalBuffer(buffer, IP_PACKET_SIZE, &sender) &&
1061 !sender.send_failure_;
1062}
1063
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001064} // namespace webrtc