blob: 154093b156ff32f929407913c8aaa67799b61560 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000011#include "webrtc/modules/rtp_rtcp/source/rtcp_sender.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
stefan@webrtc.org9354cc92012-06-07 08:10:14 +000013#include <string.h> // memcpy
niklase@google.com470e71d2011-07-07 08:21:25 +000014
Erik Språng61be2a42015-04-27 13:32:52 +020015#include "webrtc/base/checks.h"
kwiberg4485ffb2016-04-26 08:14:39 -070016#include "webrtc/base/constructormagic.h"
Peter Boströmebc0b4e2015-10-28 16:39:33 +010017#include "webrtc/base/logging.h"
tommie4f96502015-10-20 23:00:48 -070018#include "webrtc/base/trace_event.h"
terelius429c3452016-01-21 05:42:04 -080019#include "webrtc/call.h"
20#include "webrtc/call/rtc_event_log.h"
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000021#include "webrtc/common_types.h"
danilchap0219c9b2015-11-18 05:56:53 -080022#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/app.h"
danilchap50c51362015-11-22 09:03:11 -080023#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/bye.h"
danilchap2f7dea12016-01-13 02:03:04 -080024#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/compound_packet.h"
Danil Chapovalov256e5b22016-01-15 14:16:24 +010025#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_reports.h"
Danil Chapovalov5679da12016-01-15 13:19:53 +010026#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/fir.h"
danilchapa8890a52015-12-22 03:43:04 -080027#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/nack.h"
danilchapf8385ad2015-11-27 05:36:09 -080028#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/pli.h"
Danil Chapovalov97f7e132015-12-04 16:13:30 +010029#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
Danil Chapovalova5eba6c2016-01-15 12:40:15 +010030#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/remb.h"
Danil Chapovalov2c132972016-01-15 15:21:21 +010031#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rpsi.h"
Danil Chapovalov1567d0b2016-01-15 17:34:27 +010032#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sdes.h"
danilchap34ed2b92016-01-18 02:43:32 -080033#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sender_report.h"
danilchap92e677a2016-01-12 10:04:52 -080034#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sli.h"
danilchapef3d8052016-01-11 03:31:08 -080035#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbn.h"
danilchap7e8145f2016-01-11 11:49:19 -080036#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbr.h"
sprang233bd872015-09-08 13:25:16 -070037#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
tommie4f96502015-10-20 23:00:48 -070038#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
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
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:
terelius429c3452016-01-21 05:42:04 -080086 PacketContainer(Transport* transport, RtcEventLog* event_log)
87 : transport_(transport), event_log_(event_log), bytes_sent_(0) {}
Erik Språngf7c57762015-12-04 10:40:35 +010088 virtual ~PacketContainer() {
89 for (RtcpPacket* packet : appended_packets_)
90 delete packet;
91 }
92
93 void OnPacketReady(uint8_t* data, size_t length) override {
terelius429c3452016-01-21 05:42:04 -080094 if (transport_->SendRtcp(data, length)) {
Erik Språngf7c57762015-12-04 10:40:35 +010095 bytes_sent_ += length;
terelius429c3452016-01-21 05:42:04 -080096 if (event_log_) {
97 event_log_->LogRtcpPacket(kOutgoingPacket, MediaType::ANY, data,
98 length);
99 }
100 }
Erik Språngf7c57762015-12-04 10:40:35 +0100101 }
102
danilchap41befce2016-03-30 11:11:51 -0700103 size_t SendPackets(size_t max_payload_length) {
104 RTC_DCHECK_LE(max_payload_length, static_cast<size_t>(IP_PACKET_SIZE));
105 uint8_t buffer[IP_PACKET_SIZE];
106 BuildExternalBuffer(buffer, max_payload_length, this);
Erik Språngf7c57762015-12-04 10:40:35 +0100107 return bytes_sent_;
108 }
109
110 private:
111 Transport* transport_;
terelius429c3452016-01-21 05:42:04 -0800112 RtcEventLog* const event_log_;
Erik Språngf7c57762015-12-04 10:40:35 +0100113 size_t bytes_sent_;
terelius429c3452016-01-21 05:42:04 -0800114
115 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(PacketContainer);
Erik Språngf7c57762015-12-04 10:40:35 +0100116};
117
118class RTCPSender::RtcpContext {
119 public:
Erik Språng242e22b2015-05-11 10:17:43 +0200120 RtcpContext(const FeedbackState& feedback_state,
121 int32_t nack_size,
122 const uint16_t* nack_list,
123 bool repeat,
124 uint64_t picture_id,
Erik Språngf7c57762015-12-04 10:40:35 +0100125 uint32_t ntp_sec,
danilchap56036ff2016-03-22 11:14:09 -0700126 uint32_t ntp_frac)
Erik Språngf7c57762015-12-04 10:40:35 +0100127 : feedback_state_(feedback_state),
128 nack_size_(nack_size),
129 nack_list_(nack_list),
130 repeat_(repeat),
131 picture_id_(picture_id),
132 ntp_sec_(ntp_sec),
danilchap56036ff2016-03-22 11:14:09 -0700133 ntp_frac_(ntp_frac) {}
Erik Språng242e22b2015-05-11 10:17:43 +0200134
Erik Språngf7c57762015-12-04 10:40:35 +0100135 const FeedbackState& feedback_state_;
136 const int32_t nack_size_;
137 const uint16_t* nack_list_;
138 const bool repeat_;
139 const uint64_t picture_id_;
140 const uint32_t ntp_sec_;
141 const uint32_t ntp_frac_;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200142};
143
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000144RTCPSender::RTCPSender(
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000145 bool audio,
146 Clock* clock,
147 ReceiveStatistics* receive_statistics,
sprang86fd9ed2015-09-29 04:45:43 -0700148 RtcpPacketTypeCounterObserver* packet_type_counter_observer,
terelius429c3452016-01-21 05:42:04 -0800149 RtcEventLog* event_log,
sprang86fd9ed2015-09-29 04:45:43 -0700150 Transport* outgoing_transport)
Peter Boströmac547a62015-09-17 23:03:57 +0200151 : audio_(audio),
Erik Språng242e22b2015-05-11 10:17:43 +0200152 clock_(clock),
danilchap47a740b2015-12-15 00:30:07 -0800153 random_(clock_->TimeInMicroseconds()),
pbosda903ea2015-10-02 02:36:56 -0700154 method_(RtcpMode::kOff),
terelius429c3452016-01-21 05:42:04 -0800155 event_log_(event_log),
sprang86fd9ed2015-09-29 04:45:43 -0700156 transport_(outgoing_transport),
Erik Språng242e22b2015-05-11 10:17:43 +0200157 using_nack_(false),
158 sending_(false),
159 remb_enabled_(false),
Erik Språng242e22b2015-05-11 10:17:43 +0200160 next_time_to_send_rtcp_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000161 start_timestamp_(0),
162 last_rtp_timestamp_(0),
163 last_frame_capture_time_ms_(-1),
Erik Språng242e22b2015-05-11 10:17:43 +0200164 ssrc_(0),
165 remote_ssrc_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000166 receive_statistics_(receive_statistics),
niklase@google.com470e71d2011-07-07 08:21:25 +0000167
Erik Språng242e22b2015-05-11 10:17:43 +0200168 sequence_number_fir_(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000169
Erik Språng242e22b2015-05-11 10:17:43 +0200170 remb_bitrate_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000171
Erik Språng242e22b2015-05-11 10:17:43 +0200172 tmmbr_help_(),
173 tmmbr_send_(0),
174 packet_oh_send_(0),
danilchap41befce2016-03-30 11:11:51 -0700175 max_payload_length_(IP_PACKET_SIZE - 28), // IPv4 + UDP by default.
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000176
Erik Språng242e22b2015-05-11 10:17:43 +0200177 app_sub_type_(0),
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200178 app_name_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200179 app_data_(nullptr),
180 app_length_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000181
Erik Språng242e22b2015-05-11 10:17:43 +0200182 xr_send_receiver_reference_time_enabled_(false),
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000183 packet_type_counter_observer_(packet_type_counter_observer) {
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 {
danilchap56036ff2016-03-22 11:14:09 -0700208 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200209 return method_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000210}
211
skvlad1c392cc2016-04-01 14:46:44 -0700212void RTCPSender::SetRTCPStatus(RtcpMode new_method) {
danilchap56036ff2016-03-22 11:14:09 -0700213 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000214
skvlad1c392cc2016-04-01 14:46:44 -0700215 if (method_ == RtcpMode::kOff && new_method != RtcpMode::kOff) {
216 // When switching on, reschedule the next packet
217 next_time_to_send_rtcp_ =
Erik Språng242e22b2015-05-11 10:17:43 +0200218 clock_->TimeInMilliseconds() +
219 (audio_ ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
skvlad1c392cc2016-04-01 14:46:44 -0700220 }
221 method_ = new_method;
niklase@google.com470e71d2011-07-07 08:21:25 +0000222}
223
Erik Språng61be2a42015-04-27 13:32:52 +0200224bool RTCPSender::Sending() const {
danilchap56036ff2016-03-22 11:14:09 -0700225 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200226 return sending_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000227}
228
Erik Språng61be2a42015-04-27 13:32:52 +0200229int32_t RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
230 bool sending) {
231 bool sendRTCPBye = false;
232 {
danilchap56036ff2016-03-22 11:14:09 -0700233 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000234
pbosda903ea2015-10-02 02:36:56 -0700235 if (method_ != RtcpMode::kOff) {
Erik Språng242e22b2015-05-11 10:17:43 +0200236 if (sending == false && sending_ == true) {
Erik Språng61be2a42015-04-27 13:32:52 +0200237 // Trigger RTCP bye
238 sendRTCPBye = true;
239 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000240 }
Erik Språng242e22b2015-05-11 10:17:43 +0200241 sending_ = sending;
Erik Språng61be2a42015-04-27 13:32:52 +0200242 }
243 if (sendRTCPBye)
244 return SendRTCP(feedback_state, kRtcpBye);
245 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000246}
247
Erik Språng61be2a42015-04-27 13:32:52 +0200248bool RTCPSender::REMB() const {
danilchap56036ff2016-03-22 11:14:09 -0700249 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200250 return remb_enabled_;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000251}
252
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000253void RTCPSender::SetREMBStatus(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700254 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200255 remb_enabled_ = enable;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000256}
257
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000258void RTCPSender::SetREMBData(uint32_t bitrate,
259 const std::vector<uint32_t>& ssrcs) {
danilchap56036ff2016-03-22 11:14:09 -0700260 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200261 remb_bitrate_ = bitrate;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000262 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000263
Erik Språng242e22b2015-05-11 10:17:43 +0200264 if (remb_enabled_)
265 SetFlag(kRtcpRemb, false);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000266 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
267 // throttled by the caller.
Erik Språng242e22b2015-05-11 10:17:43 +0200268 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000269}
270
Erik Språng61be2a42015-04-27 13:32:52 +0200271bool RTCPSender::TMMBR() const {
danilchap56036ff2016-03-22 11:14:09 -0700272 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200273 return IsFlagPresent(RTCPPacketType::kRtcpTmmbr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000274}
275
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000276void RTCPSender::SetTMMBRStatus(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700277 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200278 if (enable) {
279 SetFlag(RTCPPacketType::kRtcpTmmbr, false);
280 } else {
281 ConsumeFlag(RTCPPacketType::kRtcpTmmbr, true);
282 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000283}
284
danilchap41befce2016-03-30 11:11:51 -0700285void RTCPSender::SetMaxPayloadLength(size_t max_payload_length) {
286 max_payload_length_ = max_payload_length;
287}
288
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000289void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
danilchap56036ff2016-03-22 11:14:09 -0700290 rtc::CritScope lock(&critical_section_rtcp_sender_);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000291 start_timestamp_ = start_timestamp;
292}
293
294void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
295 int64_t capture_time_ms) {
danilchap56036ff2016-03-22 11:14:09 -0700296 rtc::CritScope lock(&critical_section_rtcp_sender_);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000297 last_rtp_timestamp_ = rtp_timestamp;
298 if (capture_time_ms < 0) {
299 // We don't currently get a capture time from VoiceEngine.
Erik Språng242e22b2015-05-11 10:17:43 +0200300 last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000301 } else {
302 last_frame_capture_time_ms_ = capture_time_ms;
303 }
304}
305
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000306void RTCPSender::SetSSRC(uint32_t ssrc) {
danilchap56036ff2016-03-22 11:14:09 -0700307 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000308
Erik Språng242e22b2015-05-11 10:17:43 +0200309 if (ssrc_ != 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200310 // not first SetSSRC, probably due to a collision
311 // schedule a new RTCP report
312 // make sure that we send a RTP packet
Erik Språng242e22b2015-05-11 10:17:43 +0200313 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
Erik Språng61be2a42015-04-27 13:32:52 +0200314 }
Erik Språng242e22b2015-05-11 10:17:43 +0200315 ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000316}
317
Erik Språng61be2a42015-04-27 13:32:52 +0200318void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
danilchap56036ff2016-03-22 11:14:09 -0700319 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200320 remote_ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000321}
322
Peter Boström9ba52f82015-06-01 14:12:28 +0200323int32_t RTCPSender::SetCNAME(const char* c_name) {
324 if (!c_name)
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000325 return -1;
326
henrikg91d6ede2015-09-17 00:24:34 -0700327 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
danilchap56036ff2016-03-22 11:14:09 -0700328 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200329 cname_ = c_name;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000330 return 0;
331}
332
Erik Språng0ea42d32015-06-25 14:46:16 +0200333int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC, const char* c_name) {
danilchap56036ff2016-03-22 11:14:09 -0700334 RTC_DCHECK(c_name);
henrikg91d6ede2015-09-17 00:24:34 -0700335 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
danilchap56036ff2016-03-22 11:14:09 -0700336 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200337 if (csrc_cnames_.size() >= kRtpCsrcSize)
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000338 return -1;
Erik Språng0ea42d32015-06-25 14:46:16 +0200339
340 csrc_cnames_[SSRC] = c_name;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000341 return 0;
342}
343
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000344int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
danilchap56036ff2016-03-22 11:14:09 -0700345 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200346 auto it = csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000347
Erik Språng242e22b2015-05-11 10:17:43 +0200348 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000349 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200350
Erik Språng242e22b2015-05-11 10:17:43 +0200351 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000352 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000353}
354
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000355bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
danilchap162abd32015-12-10 02:39:40 -0800356 /*
357 For audio we use a fix 5 sec interval
niklase@google.com470e71d2011-07-07 08:21:25 +0000358
danilchap162abd32015-12-10 02:39:40 -0800359 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
360 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
361 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000362
363
danilchap162abd32015-12-10 02:39:40 -0800364 From RFC 3550
niklase@google.com470e71d2011-07-07 08:21:25 +0000365
danilchap162abd32015-12-10 02:39:40 -0800366 MAX RTCP BW is 5% if the session BW
367 A send report is approximately 65 bytes inc CNAME
368 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000369
danilchap162abd32015-12-10 02:39:40 -0800370 The RECOMMENDED value for the reduced minimum in seconds is 360
371 divided by the session bandwidth in kilobits/second. This minimum
372 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
niklase@google.com470e71d2011-07-07 08:21:25 +0000373
danilchap162abd32015-12-10 02:39:40 -0800374 If the participant has not yet sent an RTCP packet (the variable
375 initial is true), the constant Tmin is set to 2.5 seconds, else it
376 is set to 5 seconds.
niklase@google.com470e71d2011-07-07 08:21:25 +0000377
danilchap162abd32015-12-10 02:39:40 -0800378 The interval between RTCP packets is varied randomly over the
379 range [0.5,1.5] times the calculated interval to avoid unintended
380 synchronization of all participants
niklase@google.com470e71d2011-07-07 08:21:25 +0000381
danilchap162abd32015-12-10 02:39:40 -0800382 if we send
383 If the participant is a sender (we_sent true), the constant C is
384 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
385 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
386 number of senders.
niklase@google.com470e71d2011-07-07 08:21:25 +0000387
danilchap162abd32015-12-10 02:39:40 -0800388 if we receive only
389 If we_sent is not true, the constant C is set
390 to the average RTCP packet size divided by 75% of the RTCP
391 bandwidth. The constant n is set to the number of receivers
392 (members - senders). If the number of senders is greater than
393 25%, senders and receivers are treated together.
niklase@google.com470e71d2011-07-07 08:21:25 +0000394
danilchap162abd32015-12-10 02:39:40 -0800395 reconsideration NOT required for peer-to-peer
396 "timer reconsideration" is
397 employed. This algorithm implements a simple back-off mechanism
398 which causes users to hold back RTCP packet transmission if the
399 group sizes are increasing.
niklase@google.com470e71d2011-07-07 08:21:25 +0000400
danilchap162abd32015-12-10 02:39:40 -0800401 n = number of members
402 C = avg_size/(rtcpBW/4)
niklase@google.com470e71d2011-07-07 08:21:25 +0000403
danilchap162abd32015-12-10 02:39:40 -0800404 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
niklase@google.com470e71d2011-07-07 08:21:25 +0000405
danilchap162abd32015-12-10 02:39:40 -0800406 4. The calculated interval T is set to a number uniformly distributed
407 between 0.5 and 1.5 times the deterministic calculated interval.
niklase@google.com470e71d2011-07-07 08:21:25 +0000408
danilchap162abd32015-12-10 02:39:40 -0800409 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
410 for the fact that the timer reconsideration algorithm converges to
411 a value of the RTCP bandwidth below the intended average
412 */
niklase@google.com470e71d2011-07-07 08:21:25 +0000413
Erik Språng242e22b2015-05-11 10:17:43 +0200414 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000415
danilchap56036ff2016-03-22 11:14:09 -0700416 rtc::CritScope lock(&critical_section_rtcp_sender_);
xians@webrtc.org8738d272011-11-25 13:43:53 +0000417
pbosda903ea2015-10-02 02:36:56 -0700418 if (method_ == RtcpMode::kOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000419 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000420
Erik Språng242e22b2015-05-11 10:17:43 +0200421 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200422 // for video key-frames we want to send the RTCP before the large key-frame
423 // if we have a 100 ms margin
424 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
425 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000426
Erik Språng242e22b2015-05-11 10:17:43 +0200427 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200428 return true;
429 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200430 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200431 // wrap
432 return true;
433 }
434 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000435}
436
danilchap56036ff2016-03-22 11:14:09 -0700437std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSR(const RtcpContext& ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200438 // The timestamp of this RTCP packet should be estimated as the timestamp of
439 // the frame being captured at this moment. We are calculating that
440 // timestamp as the last frame's timestamp + the time since the last frame
441 // was captured.
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200442 uint32_t rtp_timestamp =
443 start_timestamp_ + last_rtp_timestamp_ +
444 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) *
Erik Språngf7c57762015-12-04 10:40:35 +0100445 (ctx.feedback_state_.frequency_hz / 1000);
niklase@google.com470e71d2011-07-07 08:21:25 +0000446
Erik Språngf7c57762015-12-04 10:40:35 +0100447 rtcp::SenderReport* report = new rtcp::SenderReport();
448 report->From(ssrc_);
danilchap34ed2b92016-01-18 02:43:32 -0800449 report->WithNtp(NtpTime(ctx.ntp_sec_, ctx.ntp_frac_));
Erik Språngf7c57762015-12-04 10:40:35 +0100450 report->WithRtpTimestamp(rtp_timestamp);
451 report->WithPacketCount(ctx.feedback_state_.packets_sent);
452 report->WithOctetCount(ctx.feedback_state_.media_bytes_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000453
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200454 for (auto it : report_blocks_)
Erik Språngf7c57762015-12-04 10:40:35 +0100455 report->WithReportBlock(it.second);
niklase@google.com470e71d2011-07-07 08:21:25 +0000456
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200457 report_blocks_.clear();
Erik Språngf7c57762015-12-04 10:40:35 +0100458
danilchap56036ff2016-03-22 11:14:09 -0700459 return std::unique_ptr<rtcp::RtcpPacket>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000460}
461
danilchap56036ff2016-03-22 11:14:09 -0700462std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSDES(
Erik Språngf7c57762015-12-04 10:40:35 +0100463 const RtcpContext& ctx) {
Erik Språng0ea42d32015-06-25 14:46:16 +0200464 size_t length_cname = cname_.length();
henrikg91d6ede2015-09-17 00:24:34 -0700465 RTC_CHECK_LT(length_cname, static_cast<size_t>(RTCP_CNAME_SIZE));
niklase@google.com470e71d2011-07-07 08:21:25 +0000466
Erik Språngf7c57762015-12-04 10:40:35 +0100467 rtcp::Sdes* sdes = new rtcp::Sdes();
468 sdes->WithCName(ssrc_, cname_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200469
470 for (const auto it : csrc_cnames_)
Erik Språngf7c57762015-12-04 10:40:35 +0100471 sdes->WithCName(it.first, it.second);
Erik Språng0ea42d32015-06-25 14:46:16 +0200472
danilchap56036ff2016-03-22 11:14:09 -0700473 return std::unique_ptr<rtcp::RtcpPacket>(sdes);
niklase@google.com470e71d2011-07-07 08:21:25 +0000474}
475
danilchap56036ff2016-03-22 11:14:09 -0700476std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildRR(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100477 rtcp::ReceiverReport* report = new rtcp::ReceiverReport();
478 report->From(ssrc_);
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200479 for (auto it : report_blocks_)
Erik Språngf7c57762015-12-04 10:40:35 +0100480 report->WithReportBlock(it.second);
Erik Språng61be2a42015-04-27 13:32:52 +0200481
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200482 report_blocks_.clear();
danilchap56036ff2016-03-22 11:14:09 -0700483 return std::unique_ptr<rtcp::RtcpPacket>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000484}
485
danilchap56036ff2016-03-22 11:14:09 -0700486std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildPLI(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100487 rtcp::Pli* pli = new rtcp::Pli();
488 pli->From(ssrc_);
489 pli->To(remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200490
Erik Språng242e22b2015-05-11 10:17:43 +0200491 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
492 "RTCPSender::PLI");
493 ++packet_type_counter_.pli_packets;
494 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
495 ssrc_, packet_type_counter_.pli_packets);
496
danilchap56036ff2016-03-22 11:14:09 -0700497 return std::unique_ptr<rtcp::RtcpPacket>(pli);
Erik Språng61be2a42015-04-27 13:32:52 +0200498}
499
danilchap56036ff2016-03-22 11:14:09 -0700500std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildFIR(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100501 if (!ctx.repeat_)
sprang62dae192015-08-05 02:35:35 -0700502 ++sequence_number_fir_; // Do not increase if repetition.
niklase@google.com470e71d2011-07-07 08:21:25 +0000503
Erik Språngf7c57762015-12-04 10:40:35 +0100504 rtcp::Fir* fir = new rtcp::Fir();
505 fir->From(ssrc_);
Danil Chapovalov32e590e2016-01-22 11:04:56 +0100506 fir->WithRequestTo(remote_ssrc_, sequence_number_fir_);
Erik Språng242e22b2015-05-11 10:17:43 +0200507
508 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
509 "RTCPSender::FIR");
510 ++packet_type_counter_.fir_packets;
511 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
512 ssrc_, packet_type_counter_.fir_packets);
513
danilchap56036ff2016-03-22 11:14:09 -0700514 return std::unique_ptr<rtcp::RtcpPacket>(fir);
niklase@google.com470e71d2011-07-07 08:21:25 +0000515}
516
517/*
518 0 1 2 3
519 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
520 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
521 | First | Number | PictureID |
522 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
523*/
danilchap56036ff2016-03-22 11:14:09 -0700524std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSLI(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100525 rtcp::Sli* sli = new rtcp::Sli();
526 sli->From(ssrc_);
527 sli->To(remote_ssrc_);
sprang0365a272015-08-11 01:02:37 -0700528 // Crop picture id to 6 least significant bits.
Erik Språngf7c57762015-12-04 10:40:35 +0100529 sli->WithPictureId(ctx.picture_id_ & 0x3F);
sprang0365a272015-08-11 01:02:37 -0700530
danilchap56036ff2016-03-22 11:14:09 -0700531 return std::unique_ptr<rtcp::RtcpPacket>(sli);
niklase@google.com470e71d2011-07-07 08:21:25 +0000532}
533
534/*
535 0 1 2 3
536 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
537 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
538 | PB |0| Payload Type| Native RPSI bit string |
539 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
540 | defined per codec ... | Padding (0) |
541 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
542*/
543/*
544* Note: not generic made for VP8
545*/
danilchap56036ff2016-03-22 11:14:09 -0700546std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildRPSI(
Erik Språngf7c57762015-12-04 10:40:35 +0100547 const RtcpContext& ctx) {
548 if (ctx.feedback_state_.send_payload_type == 0xFF)
549 return nullptr;
Erik Språng242e22b2015-05-11 10:17:43 +0200550
Erik Språngf7c57762015-12-04 10:40:35 +0100551 rtcp::Rpsi* rpsi = new rtcp::Rpsi();
552 rpsi->From(ssrc_);
553 rpsi->To(remote_ssrc_);
554 rpsi->WithPayloadType(ctx.feedback_state_.send_payload_type);
555 rpsi->WithPictureId(ctx.picture_id_);
sprangcf7f54d2015-08-13 04:37:42 -0700556
danilchap56036ff2016-03-22 11:14:09 -0700557 return std::unique_ptr<rtcp::RtcpPacket>(rpsi);
niklase@google.com470e71d2011-07-07 08:21:25 +0000558}
559
danilchap56036ff2016-03-22 11:14:09 -0700560std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildREMB(
Erik Språngf7c57762015-12-04 10:40:35 +0100561 const RtcpContext& ctx) {
562 rtcp::Remb* remb = new rtcp::Remb();
563 remb->From(ssrc_);
sprangdd4edc52015-08-21 04:21:51 -0700564 for (uint32_t ssrc : remb_ssrcs_)
Erik Språngf7c57762015-12-04 10:40:35 +0100565 remb->AppliesTo(ssrc);
566 remb->WithBitrateBps(remb_bitrate_);
Erik Språng61be2a42015-04-27 13:32:52 +0200567
Erik Språng242e22b2015-05-11 10:17:43 +0200568 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
569 "RTCPSender::REMB");
570
danilchap56036ff2016-03-22 11:14:09 -0700571 return std::unique_ptr<rtcp::RtcpPacket>(remb);
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000572}
573
Erik Språng61be2a42015-04-27 13:32:52 +0200574void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
danilchap56036ff2016-03-22 11:14:09 -0700575 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200576 tmmbr_send_ = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000577}
578
danilchap56036ff2016-03-22 11:14:09 -0700579std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBR(
Erik Språngf7c57762015-12-04 10:40:35 +0100580 const RtcpContext& ctx) {
581 if (ctx.feedback_state_.module == nullptr)
582 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200583 // Before sending the TMMBR check the received TMMBN, only an owner is
584 // allowed to raise the bitrate:
585 // * If the sender is an owner of the TMMBN -> send TMMBR
586 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000587
Erik Språng61be2a42015-04-27 13:32:52 +0200588 // get current bounding set from RTCP receiver
589 bool tmmbrOwner = false;
590 // store in candidateSet, allocates one extra slot
Erik Språng242e22b2015-05-11 10:17:43 +0200591 TMMBRSet* candidateSet = tmmbr_help_.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000592
Erik Språng242e22b2015-05-11 10:17:43 +0200593 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
594 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
Erik Språng61be2a42015-04-27 13:32:52 +0200595 // since RTCPreceiver is not doing the reverse we should be fine
596 int32_t lengthOfBoundingSet =
danilchap6db6cdc2015-12-15 02:54:47 -0800597 ctx.feedback_state_.module->BoundingSet(&tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +0000598
Erik Språng61be2a42015-04-27 13:32:52 +0200599 if (lengthOfBoundingSet > 0) {
600 for (int32_t i = 0; i < lengthOfBoundingSet; i++) {
Erik Språng242e22b2015-05-11 10:17:43 +0200601 if (candidateSet->Tmmbr(i) == tmmbr_send_ &&
602 candidateSet->PacketOH(i) == packet_oh_send_) {
Erik Språngf7c57762015-12-04 10:40:35 +0100603 // Do not send the same tuple.
604 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200605 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000606 }
Erik Språng61be2a42015-04-27 13:32:52 +0200607 if (!tmmbrOwner) {
608 // use received bounding set as candidate set
609 // add current tuple
Erik Språng242e22b2015-05-11 10:17:43 +0200610 candidateSet->SetEntry(lengthOfBoundingSet, tmmbr_send_, packet_oh_send_,
611 ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200612 int numCandidates = lengthOfBoundingSet + 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000613
Erik Språng61be2a42015-04-27 13:32:52 +0200614 // find bounding set
Erik Språngf7c57762015-12-04 10:40:35 +0100615 TMMBRSet* boundingSet = nullptr;
Erik Språng242e22b2015-05-11 10:17:43 +0200616 int numBoundingSet = tmmbr_help_.FindTMMBRBoundingSet(boundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200617 if (numBoundingSet > 0 || numBoundingSet <= numCandidates)
Erik Språng242e22b2015-05-11 10:17:43 +0200618 tmmbrOwner = tmmbr_help_.IsOwner(ssrc_, numBoundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200619 if (!tmmbrOwner) {
Erik Språngf7c57762015-12-04 10:40:35 +0100620 // Did not enter bounding set, no meaning to send this request.
621 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200622 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000623 }
Erik Språng61be2a42015-04-27 13:32:52 +0200624 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000625
Erik Språngf7c57762015-12-04 10:40:35 +0100626 if (!tmmbr_send_)
627 return nullptr;
sprang81a3e602015-08-21 05:30:11 -0700628
Erik Språngf7c57762015-12-04 10:40:35 +0100629 rtcp::Tmmbr* tmmbr = new rtcp::Tmmbr();
630 tmmbr->From(ssrc_);
danilchapf174e3a2016-02-05 04:56:36 -0800631 rtcp::TmmbItem request;
632 request.set_ssrc(remote_ssrc_);
633 request.set_bitrate_bps(tmmbr_send_ * 1000);
634 request.set_packet_overhead(packet_oh_send_);
635 tmmbr->WithTmmbr(request);
Erik Språngf7c57762015-12-04 10:40:35 +0100636
danilchap56036ff2016-03-22 11:14:09 -0700637 return std::unique_ptr<rtcp::RtcpPacket>(tmmbr);
Erik Språng61be2a42015-04-27 13:32:52 +0200638}
639
danilchap56036ff2016-03-22 11:14:09 -0700640std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBN(
Erik Språngf7c57762015-12-04 10:40:35 +0100641 const RtcpContext& ctx) {
Erik Språng242e22b2015-05-11 10:17:43 +0200642 TMMBRSet* boundingSet = tmmbr_help_.BoundingSetToSend();
Erik Språngf7c57762015-12-04 10:40:35 +0100643 if (boundingSet == nullptr)
644 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200645
Erik Språngf7c57762015-12-04 10:40:35 +0100646 rtcp::Tmmbn* tmmbn = new rtcp::Tmmbn();
647 tmmbn->From(ssrc_);
sprangd83df502015-08-27 01:05:08 -0700648 for (uint32_t i = 0; i < boundingSet->lengthOfSet(); i++) {
649 if (boundingSet->Tmmbr(i) > 0) {
Erik Språngf7c57762015-12-04 10:40:35 +0100650 tmmbn->WithTmmbr(boundingSet->Ssrc(i), boundingSet->Tmmbr(i),
651 boundingSet->PacketOH(i));
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000652 }
Erik Språng61be2a42015-04-27 13:32:52 +0200653 }
sprangd83df502015-08-27 01:05:08 -0700654
danilchap56036ff2016-03-22 11:14:09 -0700655 return std::unique_ptr<rtcp::RtcpPacket>(tmmbn);
niklase@google.com470e71d2011-07-07 08:21:25 +0000656}
657
danilchap56036ff2016-03-22 11:14:09 -0700658std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildAPP(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100659 rtcp::App* app = new rtcp::App();
660 app->From(ssrc_);
661 app->WithSubType(app_sub_type_);
662 app->WithName(app_name_);
663 app->WithData(app_data_.get(), app_length_);
Erik Språng521875a2015-09-01 10:11:16 +0200664
danilchap56036ff2016-03-22 11:14:09 -0700665 return std::unique_ptr<rtcp::RtcpPacket>(app);
Erik Språng61be2a42015-04-27 13:32:52 +0200666}
667
danilchap56036ff2016-03-22 11:14:09 -0700668std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildNACK(
Erik Språngf7c57762015-12-04 10:40:35 +0100669 const RtcpContext& ctx) {
670 rtcp::Nack* nack = new rtcp::Nack();
671 nack->From(ssrc_);
672 nack->To(remote_ssrc_);
673 nack->WithList(ctx.nack_list_, ctx.nack_size_);
Erik Språng61be2a42015-04-27 13:32:52 +0200674
675 // Report stats.
676 NACKStringBuilder stringBuilder;
Erik Språngf7c57762015-12-04 10:40:35 +0100677 for (int idx = 0; idx < ctx.nack_size_; ++idx) {
678 stringBuilder.PushNACK(ctx.nack_list_[idx]);
679 nack_stats_.ReportRequest(ctx.nack_list_[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +0200680 }
Erik Språng61be2a42015-04-27 13:32:52 +0200681 packet_type_counter_.nack_requests = nack_stats_.requests();
682 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +0200683
684 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
685 "RTCPSender::NACK", "nacks",
686 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
687 ++packet_type_counter_.nack_packets;
688 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
689 ssrc_, packet_type_counter_.nack_packets);
690
danilchap56036ff2016-03-22 11:14:09 -0700691 return std::unique_ptr<rtcp::RtcpPacket>(nack);
Erik Språng61be2a42015-04-27 13:32:52 +0200692}
693
danilchap56036ff2016-03-22 11:14:09 -0700694std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildBYE(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100695 rtcp::Bye* bye = new rtcp::Bye();
696 bye->From(ssrc_);
sprangd8ee4f92015-08-24 03:25:19 -0700697 for (uint32_t csrc : csrcs_)
Erik Språngf7c57762015-12-04 10:40:35 +0100698 bye->WithCsrc(csrc);
sprangd8ee4f92015-08-24 03:25:19 -0700699
danilchap56036ff2016-03-22 11:14:09 -0700700 return std::unique_ptr<rtcp::RtcpPacket>(bye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000701}
702
danilchap56036ff2016-03-22 11:14:09 -0700703std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildReceiverReferenceTime(
Erik Språngf7c57762015-12-04 10:40:35 +0100704 const RtcpContext& ctx) {
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000705
Danil Chapovalov256e5b22016-01-15 14:16:24 +0100706 rtcp::ExtendedReports* xr = new rtcp::ExtendedReports();
Erik Språngf7c57762015-12-04 10:40:35 +0100707 xr->From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000708
Erik Språngca28fdc2015-08-31 14:00:50 +0200709 rtcp::Rrtr rrtr;
Danil Chapovalovfc47ed62015-12-07 14:46:35 +0100710 rrtr.WithNtp(NtpTime(ctx.ntp_sec_, ctx.ntp_frac_));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000711
danilchapde138822016-01-29 11:26:14 -0800712 xr->WithRrtr(rrtr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000713
Erik Språngca28fdc2015-08-31 14:00:50 +0200714 // TODO(sprang): Merge XR report sending to contain all of RRTR, DLRR, VOIP?
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000715
danilchap56036ff2016-03-22 11:14:09 -0700716 return std::unique_ptr<rtcp::RtcpPacket>(xr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000717}
718
danilchap56036ff2016-03-22 11:14:09 -0700719std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildDlrr(
Erik Språngf7c57762015-12-04 10:40:35 +0100720 const RtcpContext& ctx) {
Danil Chapovalov256e5b22016-01-15 14:16:24 +0100721 rtcp::ExtendedReports* xr = new rtcp::ExtendedReports();
Erik Språngf7c57762015-12-04 10:40:35 +0100722 xr->From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000723
Erik Språngca28fdc2015-08-31 14:00:50 +0200724 rtcp::Dlrr dlrr;
Erik Språngf7c57762015-12-04 10:40:35 +0100725 const RtcpReceiveTimeInfo& info = ctx.feedback_state_.last_xr_rr;
Erik Språngca28fdc2015-08-31 14:00:50 +0200726 dlrr.WithDlrrItem(info.sourceSSRC, info.lastRR, info.delaySinceLastRR);
727
danilchapde138822016-01-29 11:26:14 -0800728 xr->WithDlrr(dlrr);
Erik Språngca28fdc2015-08-31 14:00:50 +0200729
danilchap56036ff2016-03-22 11:14:09 -0700730 return std::unique_ptr<rtcp::RtcpPacket>(xr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000731}
732
Erik Språng242e22b2015-05-11 10:17:43 +0200733// TODO(sprang): Add a unit test for this, or remove if the code isn't used.
danilchap56036ff2016-03-22 11:14:09 -0700734std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildVoIPMetric(
Erik Språngf7c57762015-12-04 10:40:35 +0100735 const RtcpContext& context) {
Danil Chapovalov256e5b22016-01-15 14:16:24 +0100736 rtcp::ExtendedReports* xr = new rtcp::ExtendedReports();
Erik Språngf7c57762015-12-04 10:40:35 +0100737 xr->From(ssrc_);
Erik Språngca28fdc2015-08-31 14:00:50 +0200738
739 rtcp::VoipMetric voip;
740 voip.To(remote_ssrc_);
danilchap91941ae2015-12-15 07:06:36 -0800741 voip.WithVoipMetric(xr_voip_metric_);
Erik Språngca28fdc2015-08-31 14:00:50 +0200742
danilchapde138822016-01-29 11:26:14 -0800743 xr->WithVoipMetric(voip);
Erik Språngca28fdc2015-08-31 14:00:50 +0200744
danilchap56036ff2016-03-22 11:14:09 -0700745 return std::unique_ptr<rtcp::RtcpPacket>(xr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000746}
747
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000748int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200749 RTCPPacketType packetType,
750 int32_t nack_size,
751 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000752 bool repeat,
753 uint64_t pictureID) {
Erik Språng242e22b2015-05-11 10:17:43 +0200754 return SendCompoundRTCP(
755 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
756 nack_size, nack_list, repeat, pictureID);
757}
758
759int32_t RTCPSender::SendCompoundRTCP(
760 const FeedbackState& feedback_state,
Erik Språngf7c57762015-12-04 10:40:35 +0100761 const std::set<RTCPPacketType>& packet_types,
Erik Språng242e22b2015-05-11 10:17:43 +0200762 int32_t nack_size,
763 const uint16_t* nack_list,
764 bool repeat,
765 uint64_t pictureID) {
terelius429c3452016-01-21 05:42:04 -0800766 PacketContainer container(transport_, event_log_);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000767 {
danilchap56036ff2016-03-22 11:14:09 -0700768 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbosda903ea2015-10-02 02:36:56 -0700769 if (method_ == RtcpMode::kOff) {
Erik Språng61be2a42015-04-27 13:32:52 +0200770 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
771 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +0000772 }
Erik Språngf7c57762015-12-04 10:40:35 +0100773
774 // We need to send our NTP even if we haven't received any reports.
775 uint32_t ntp_sec;
776 uint32_t ntp_frac;
777 clock_->CurrentNtp(ntp_sec, ntp_frac);
778 RtcpContext context(feedback_state, nack_size, nack_list, repeat, pictureID,
danilchap56036ff2016-03-22 11:14:09 -0700779 ntp_sec, ntp_frac);
Erik Språngf7c57762015-12-04 10:40:35 +0100780
781 PrepareReport(packet_types, feedback_state);
782
danilchap56036ff2016-03-22 11:14:09 -0700783 std::unique_ptr<rtcp::RtcpPacket> packet_bye;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800784
Erik Språngf7c57762015-12-04 10:40:35 +0100785 auto it = report_flags_.begin();
786 while (it != report_flags_.end()) {
787 auto builder_it = builders_.find(it->type);
788 RTC_DCHECK(builder_it != builders_.end());
789 if (it->is_volatile) {
790 report_flags_.erase(it++);
791 } else {
792 ++it;
793 }
794
795 BuilderFunc func = builder_it->second;
danilchap56036ff2016-03-22 11:14:09 -0700796 std::unique_ptr<rtcp::RtcpPacket> packet = (this->*func)(context);
Erik Språngf7c57762015-12-04 10:40:35 +0100797 if (packet.get() == nullptr)
798 return -1;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800799 // If there is a BYE, don't append now - save it and append it
800 // at the end later.
801 if (builder_it->first == kRtcpBye) {
802 packet_bye = std::move(packet);
803 } else {
804 container.Append(packet.release());
805 }
806 }
807
808 // Append the BYE now at the end
809 if (packet_bye) {
810 container.Append(packet_bye.release());
Erik Språngf7c57762015-12-04 10:40:35 +0100811 }
812
813 if (packet_type_counter_observer_ != nullptr) {
814 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
815 remote_ssrc_, packet_type_counter_);
816 }
817
818 RTC_DCHECK(AllVolatileFlagsConsumed());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000819 }
Erik Språng61be2a42015-04-27 13:32:52 +0200820
danilchap41befce2016-03-30 11:11:51 -0700821 size_t bytes_sent = container.SendPackets(max_payload_length_);
Erik Språngf7c57762015-12-04 10:40:35 +0100822 return bytes_sent == 0 ? -1 : 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000823}
824
Erik Språngf7c57762015-12-04 10:40:35 +0100825void RTCPSender::PrepareReport(const std::set<RTCPPacketType>& packetTypes,
826 const FeedbackState& feedback_state) {
Erik Språng242e22b2015-05-11 10:17:43 +0200827 // Add all flags as volatile. Non volatile entries will not be overwritten
828 // and all new volatile flags added will be consumed by the end of this call.
829 SetFlags(packetTypes, true);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000830
Erik Språng61be2a42015-04-27 13:32:52 +0200831 if (packet_type_counter_.first_packet_time_ms == -1)
Erik Språng242e22b2015-05-11 10:17:43 +0200832 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språng61be2a42015-04-27 13:32:52 +0200833
Erik Språng242e22b2015-05-11 10:17:43 +0200834 bool generate_report;
835 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
836 // Report type already explicitly set, don't automatically populate.
837 generate_report = true;
henrikg91d6ede2015-09-17 00:24:34 -0700838 RTC_DCHECK(ConsumeFlag(kRtcpReport) == false);
Erik Språng242e22b2015-05-11 10:17:43 +0200839 } else {
840 generate_report =
pbosda903ea2015-10-02 02:36:56 -0700841 (ConsumeFlag(kRtcpReport) && method_ == RtcpMode::kReducedSize) ||
842 method_ == RtcpMode::kCompound;
Erik Språng242e22b2015-05-11 10:17:43 +0200843 if (generate_report)
844 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000845 }
846
Erik Språng0ea42d32015-06-25 14:46:16 +0200847 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
Erik Språng242e22b2015-05-11 10:17:43 +0200848 SetFlag(kRtcpSdes, true);
849
Erik Språng242e22b2015-05-11 10:17:43 +0200850 if (generate_report) {
851 if (!sending_ && xr_send_receiver_reference_time_enabled_)
852 SetFlag(kRtcpXrReceiverReferenceTime, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200853 if (feedback_state.has_last_xr_rr)
Erik Språng242e22b2015-05-11 10:17:43 +0200854 SetFlag(kRtcpXrDlrrReportBlock, true);
855
856 // generate next time to send an RTCP report
danilchap47a740b2015-12-15 00:30:07 -0800857 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000858
danilchap47a740b2015-12-15 00:30:07 -0800859 if (!audio_) {
Erik Språng242e22b2015-05-11 10:17:43 +0200860 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200861 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
862 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
863 if (send_bitrate_kbit != 0)
864 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000865 }
Erik Språng61be2a42015-04-27 13:32:52 +0200866 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
867 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
Erik Språng61be2a42015-04-27 13:32:52 +0200868 }
danilchap47a740b2015-12-15 00:30:07 -0800869 // The interval between RTCP packets is varied randomly over the
870 // range [1/2,3/2] times the calculated interval.
871 uint32_t timeToNext =
872 random_.Rand(minIntervalMs * 1 / 2, minIntervalMs * 3 / 2);
Erik Språng242e22b2015-05-11 10:17:43 +0200873 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000874
Per83d09102016-04-15 14:59:13 +0200875 if (receive_statistics_) {
876 StatisticianMap statisticians =
877 receive_statistics_->GetActiveStatisticians();
878 RTC_DCHECK(report_blocks_.empty());
879 for (auto& it : statisticians) {
880 AddReportBlock(feedback_state, it.first, it.second);
881 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000882 }
883 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000884}
885
danilchapa72e7342015-12-22 08:07:45 -0800886bool RTCPSender::AddReportBlock(const FeedbackState& feedback_state,
887 uint32_t ssrc,
888 StreamStatistician* statistician) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000889 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000890 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000891 if (!statistician->GetStatistics(&stats, true))
892 return false;
danilchapa72e7342015-12-22 08:07:45 -0800893
894 if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) {
895 LOG(LS_WARNING) << "Too many report blocks.";
896 return false;
897 }
898 RTC_DCHECK(report_blocks_.find(ssrc) == report_blocks_.end());
899 rtcp::ReportBlock* block = &report_blocks_[ssrc];
900 block->To(ssrc);
901 block->WithFractionLost(stats.fraction_lost);
902 if (!block->WithCumulativeLost(stats.cumulative_lost)) {
903 report_blocks_.erase(ssrc);
904 LOG(LS_WARNING) << "Cumulative lost is oversized.";
905 return false;
906 }
907 block->WithExtHighestSeqNum(stats.extended_max_sequence_number);
908 block->WithJitter(stats.jitter);
909 block->WithLastSr(feedback_state.remote_sr);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000910
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200911 // TODO(sprang): Do we really need separate time stamps for each report?
912 // Get our NTP as late as possible to avoid a race.
913 uint32_t ntp_secs;
914 uint32_t ntp_frac;
915 clock_->CurrentNtp(ntp_secs, ntp_frac);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000916
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200917 // Delay since last received report.
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000918 if ((feedback_state.last_rr_ntp_secs != 0) ||
919 (feedback_state.last_rr_ntp_frac != 0)) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200920 // Get the 16 lowest bits of seconds and the 16 highest bits of fractions.
921 uint32_t now = ntp_secs & 0x0000FFFF;
Erik Språng61be2a42015-04-27 13:32:52 +0200922 now <<= 16;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200923 now += (ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000924
Erik Språng61be2a42015-04-27 13:32:52 +0200925 uint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
926 receiveTime <<= 16;
927 receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000928
danilchapa72e7342015-12-22 08:07:45 -0800929 block->WithDelayLastSr(now - receiveTime);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000930 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000931 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000932}
933
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000934void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
danilchap56036ff2016-03-22 11:14:09 -0700935 RTC_DCHECK_LE(csrcs.size(), static_cast<size_t>(kRtpCsrcSize));
936 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000937 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +0000938}
939
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000940int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
941 uint32_t name,
942 const uint8_t* data,
943 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +0200944 if (length % 4 != 0) {
945 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
946 return -1;
947 }
danilchap56036ff2016-03-22 11:14:09 -0700948 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000949
Erik Språng242e22b2015-05-11 10:17:43 +0200950 SetFlag(kRtcpApp, true);
951 app_sub_type_ = subType;
952 app_name_ = name;
953 app_data_.reset(new uint8_t[length]);
954 app_length_ = length;
955 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +0200956 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000957}
958
Erik Språng61be2a42015-04-27 13:32:52 +0200959int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
danilchap56036ff2016-03-22 11:14:09 -0700960 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200961 memcpy(&xr_voip_metric_, VoIPMetric, sizeof(RTCPVoIPMetric));
niklase@google.com470e71d2011-07-07 08:21:25 +0000962
Erik Språng242e22b2015-05-11 10:17:43 +0200963 SetFlag(kRtcpXrVoipMetric, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200964 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000965}
966
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000967void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700968 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200969 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000970}
971
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000972bool RTCPSender::RtcpXrReceiverReferenceTime() const {
danilchap56036ff2016-03-22 11:14:09 -0700973 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200974 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000975}
976
niklase@google.com470e71d2011-07-07 08:21:25 +0000977// no callbacks allowed inside this function
Peter Boström9d0c4322016-02-16 17:59:27 +0100978int32_t RTCPSender::SetTMMBN(const TMMBRSet* boundingSet) {
danilchap56036ff2016-03-22 11:14:09 -0700979 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000980
Peter Boström9d0c4322016-02-16 17:59:27 +0100981 if (0 == tmmbr_help_.SetTMMBRBoundingSetToSend(boundingSet)) {
Erik Språng242e22b2015-05-11 10:17:43 +0200982 SetFlag(kRtcpTmmbn, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200983 return 0;
984 }
985 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000986}
Erik Språng61be2a42015-04-27 13:32:52 +0200987
Erik Språng242e22b2015-05-11 10:17:43 +0200988void RTCPSender::SetFlag(RTCPPacketType type, bool is_volatile) {
989 report_flags_.insert(ReportFlag(type, is_volatile));
990}
991
992void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
993 bool is_volatile) {
994 for (RTCPPacketType type : types)
995 SetFlag(type, is_volatile);
996}
997
998bool RTCPSender::IsFlagPresent(RTCPPacketType type) const {
999 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
1000}
1001
1002bool RTCPSender::ConsumeFlag(RTCPPacketType type, bool forced) {
1003 auto it = report_flags_.find(ReportFlag(type, false));
1004 if (it == report_flags_.end())
1005 return false;
1006 if (it->is_volatile || forced)
1007 report_flags_.erase((it));
1008 return true;
1009}
1010
1011bool RTCPSender::AllVolatileFlagsConsumed() const {
1012 for (const ReportFlag& flag : report_flags_) {
1013 if (flag.is_volatile)
1014 return false;
1015 }
1016 return true;
1017}
1018
sprang233bd872015-09-08 13:25:16 -07001019bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
sprang233bd872015-09-08 13:25:16 -07001020 class Sender : public rtcp::RtcpPacket::PacketReadyCallback {
1021 public:
terelius429c3452016-01-21 05:42:04 -08001022 Sender(Transport* transport, RtcEventLog* event_log)
1023 : transport_(transport), event_log_(event_log), send_failure_(false) {}
sprang233bd872015-09-08 13:25:16 -07001024
1025 void OnPacketReady(uint8_t* data, size_t length) override {
terelius429c3452016-01-21 05:42:04 -08001026 if (transport_->SendRtcp(data, length)) {
1027 if (event_log_) {
1028 event_log_->LogRtcpPacket(kOutgoingPacket, MediaType::ANY, data,
1029 length);
1030 }
1031 } else {
sprang233bd872015-09-08 13:25:16 -07001032 send_failure_ = true;
terelius429c3452016-01-21 05:42:04 -08001033 }
sprang233bd872015-09-08 13:25:16 -07001034 }
1035
1036 Transport* const transport_;
terelius429c3452016-01-21 05:42:04 -08001037 RtcEventLog* const event_log_;
sprang233bd872015-09-08 13:25:16 -07001038 bool send_failure_;
terelius429c3452016-01-21 05:42:04 -08001039 // TODO(terelius): We would like to
1040 // RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(Sender);
1041 // but we can't because of an incorrect warning (C4822) in MVS 2013.
1042 } sender(transport_, event_log_);
sprang233bd872015-09-08 13:25:16 -07001043
danilchap41befce2016-03-30 11:11:51 -07001044 RTC_DCHECK_LE(max_payload_length_, static_cast<size_t>(IP_PACKET_SIZE));
sprang233bd872015-09-08 13:25:16 -07001045 uint8_t buffer[IP_PACKET_SIZE];
danilchap41befce2016-03-30 11:11:51 -07001046 return packet.BuildExternalBuffer(buffer, max_payload_length_, &sender) &&
sprang233bd872015-09-08 13:25:16 -07001047 !sender.send_failure_;
1048}
1049
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001050} // namespace webrtc