blob: 48a016d70a577a5c47bf74bf7410bf9d054c81cf [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
Danil Chapovalov70ffead2016-07-20 15:26:59 +020015#include <utility>
16
Erik Språng61be2a42015-04-27 13:32:52 +020017#include "webrtc/base/checks.h"
kwiberg4485ffb2016-04-26 08:14:39 -070018#include "webrtc/base/constructormagic.h"
Peter Boströmebc0b4e2015-10-28 16:39:33 +010019#include "webrtc/base/logging.h"
tommie4f96502015-10-20 23:00:48 -070020#include "webrtc/base/trace_event.h"
ossuf515ab82016-12-07 04:52:58 -080021#include "webrtc/call/call.h"
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000022#include "webrtc/common_types.h"
skvladcc91d282016-10-03 18:31:22 -070023#include "webrtc/logging/rtc_event_log/rtc_event_log.h"
danilchap0219c9b2015-11-18 05:56:53 -080024#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/app.h"
danilchap50c51362015-11-22 09:03:11 -080025#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/bye.h"
danilchap2f7dea12016-01-13 02:03:04 -080026#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/compound_packet.h"
Danil Chapovalov256e5b22016-01-15 14:16:24 +010027#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_reports.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"
Danil Chapovalov2c132972016-01-15 15:21:21 +010033#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rpsi.h"
Danil Chapovalov1567d0b2016-01-15 17:34:27 +010034#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sdes.h"
danilchap34ed2b92016-01-18 02:43:32 -080035#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sender_report.h"
danilchap92e677a2016-01-12 10:04:52 -080036#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sli.h"
danilchapef3d8052016-01-11 03:31:08 -080037#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbn.h"
danilchap7e8145f2016-01-11 11:49:19 -080038#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbr.h"
sprang233bd872015-09-08 13:25:16 -070039#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
tommie4f96502015-10-20 23:00:48 -070040#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
danilchap13deaad2016-05-24 13:25:27 -070041#include "webrtc/modules/rtp_rtcp/source/tmmbr_help.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000042
niklase@google.com470e71d2011-07-07 08:21:25 +000043namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000044
sprang5e38c962016-12-01 05:18:09 -080045namespace {
46const uint32_t kRtcpAnyExtendedReports =
47 kRtcpXrVoipMetric | kRtcpXrReceiverReferenceTime | kRtcpXrDlrrReportBlock |
48 kRtcpXrTargetBitrate;
49} // namespace
50
Erik Språng61be2a42015-04-27 13:32:52 +020051NACKStringBuilder::NACKStringBuilder()
danilchap162abd32015-12-10 02:39:40 -080052 : stream_(""), count_(0), prevNack_(0), consecutive_(false) {}
edjee@google.com79b02892013-04-04 19:43:34 +000053
pbos@webrtc.orgf3e4cee2013-07-31 15:17:19 +000054NACKStringBuilder::~NACKStringBuilder() {}
55
danilchap162abd32015-12-10 02:39:40 -080056void NACKStringBuilder::PushNACK(uint16_t nack) {
Erik Språng242e22b2015-05-11 10:17:43 +020057 if (count_ == 0) {
58 stream_ << nack;
59 } else if (nack == prevNack_ + 1) {
60 consecutive_ = true;
Erik Språng61be2a42015-04-27 13:32:52 +020061 } else {
Erik Språng242e22b2015-05-11 10:17:43 +020062 if (consecutive_) {
63 stream_ << "-" << prevNack_;
64 consecutive_ = false;
edjee@google.com79b02892013-04-04 19:43:34 +000065 }
Erik Språng242e22b2015-05-11 10:17:43 +020066 stream_ << "," << nack;
Erik Språng61be2a42015-04-27 13:32:52 +020067 }
Erik Språng242e22b2015-05-11 10:17:43 +020068 count_++;
69 prevNack_ = nack;
edjee@google.com79b02892013-04-04 19:43:34 +000070}
71
Erik Språng61be2a42015-04-27 13:32:52 +020072std::string NACKStringBuilder::GetResult() {
Erik Språng242e22b2015-05-11 10:17:43 +020073 if (consecutive_) {
74 stream_ << "-" << prevNack_;
75 consecutive_ = false;
Erik Språng61be2a42015-04-27 13:32:52 +020076 }
Erik Språng242e22b2015-05-11 10:17:43 +020077 return stream_.str();
edjee@google.com79b02892013-04-04 19:43:34 +000078}
79
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000080RTCPSender::FeedbackState::FeedbackState()
81 : send_payload_type(0),
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +000082 packets_sent(0),
83 media_bytes_sent(0),
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000084 send_bitrate(0),
85 last_rr_ntp_secs(0),
86 last_rr_ntp_frac(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000087 remote_sr(0),
Erik Språng61be2a42015-04-27 13:32:52 +020088 has_last_xr_rr(false),
danilchap162abd32015-12-10 02:39:40 -080089 module(nullptr) {}
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000090
danilchap2f7dea12016-01-13 02:03:04 -080091class PacketContainer : public rtcp::CompoundPacket,
Erik Språngf7c57762015-12-04 10:40:35 +010092 public rtcp::RtcpPacket::PacketReadyCallback {
93 public:
terelius429c3452016-01-21 05:42:04 -080094 PacketContainer(Transport* transport, RtcEventLog* event_log)
95 : transport_(transport), event_log_(event_log), bytes_sent_(0) {}
Erik Språngf7c57762015-12-04 10:40:35 +010096 virtual ~PacketContainer() {
97 for (RtcpPacket* packet : appended_packets_)
98 delete packet;
99 }
100
101 void OnPacketReady(uint8_t* data, size_t length) override {
terelius429c3452016-01-21 05:42:04 -0800102 if (transport_->SendRtcp(data, length)) {
Erik Språngf7c57762015-12-04 10:40:35 +0100103 bytes_sent_ += length;
terelius429c3452016-01-21 05:42:04 -0800104 if (event_log_) {
105 event_log_->LogRtcpPacket(kOutgoingPacket, MediaType::ANY, data,
106 length);
107 }
108 }
Erik Språngf7c57762015-12-04 10:40:35 +0100109 }
110
danilchap41befce2016-03-30 11:11:51 -0700111 size_t SendPackets(size_t max_payload_length) {
kwiberg352444f2016-11-28 15:58:53 -0800112 RTC_DCHECK_LE(max_payload_length, IP_PACKET_SIZE);
danilchap41befce2016-03-30 11:11:51 -0700113 uint8_t buffer[IP_PACKET_SIZE];
114 BuildExternalBuffer(buffer, max_payload_length, this);
Erik Språngf7c57762015-12-04 10:40:35 +0100115 return bytes_sent_;
116 }
117
118 private:
119 Transport* transport_;
terelius429c3452016-01-21 05:42:04 -0800120 RtcEventLog* const event_log_;
Erik Språngf7c57762015-12-04 10:40:35 +0100121 size_t bytes_sent_;
terelius429c3452016-01-21 05:42:04 -0800122
123 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(PacketContainer);
Erik Språngf7c57762015-12-04 10:40:35 +0100124};
125
126class RTCPSender::RtcpContext {
127 public:
Erik Språng242e22b2015-05-11 10:17:43 +0200128 RtcpContext(const FeedbackState& feedback_state,
129 int32_t nack_size,
130 const uint16_t* nack_list,
Erik Språng242e22b2015-05-11 10:17:43 +0200131 uint64_t picture_id,
danilchap51813b32016-12-16 02:44:36 -0800132 NtpTime now)
Erik Språngf7c57762015-12-04 10:40:35 +0100133 : feedback_state_(feedback_state),
134 nack_size_(nack_size),
135 nack_list_(nack_list),
Erik Språngf7c57762015-12-04 10:40:35 +0100136 picture_id_(picture_id),
danilchap51813b32016-12-16 02:44:36 -0800137 now_(now) {}
Erik Språng242e22b2015-05-11 10:17:43 +0200138
Erik Språngf7c57762015-12-04 10:40:35 +0100139 const FeedbackState& feedback_state_;
140 const int32_t nack_size_;
141 const uint16_t* nack_list_;
Erik Språngf7c57762015-12-04 10:40:35 +0100142 const uint64_t picture_id_;
danilchap51813b32016-12-16 02:44:36 -0800143 const NtpTime now_;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200144};
145
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000146RTCPSender::RTCPSender(
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000147 bool audio,
148 Clock* clock,
149 ReceiveStatistics* receive_statistics,
sprang86fd9ed2015-09-29 04:45:43 -0700150 RtcpPacketTypeCounterObserver* packet_type_counter_observer,
terelius429c3452016-01-21 05:42:04 -0800151 RtcEventLog* event_log,
sprang86fd9ed2015-09-29 04:45:43 -0700152 Transport* outgoing_transport)
Peter Boströmac547a62015-09-17 23:03:57 +0200153 : audio_(audio),
Erik Språng242e22b2015-05-11 10:17:43 +0200154 clock_(clock),
danilchap47a740b2015-12-15 00:30:07 -0800155 random_(clock_->TimeInMicroseconds()),
pbosda903ea2015-10-02 02:36:56 -0700156 method_(RtcpMode::kOff),
terelius429c3452016-01-21 05:42:04 -0800157 event_log_(event_log),
sprang86fd9ed2015-09-29 04:45:43 -0700158 transport_(outgoing_transport),
Erik Språng242e22b2015-05-11 10:17:43 +0200159 using_nack_(false),
160 sending_(false),
161 remb_enabled_(false),
Erik Språng242e22b2015-05-11 10:17:43 +0200162 next_time_to_send_rtcp_(0),
danilchap71fead22016-08-18 02:01:49 -0700163 timestamp_offset_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000164 last_rtp_timestamp_(0),
165 last_frame_capture_time_ms_(-1),
Erik Språng242e22b2015-05-11 10:17:43 +0200166 ssrc_(0),
167 remote_ssrc_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000168 receive_statistics_(receive_statistics),
niklase@google.com470e71d2011-07-07 08:21:25 +0000169
Erik Språng242e22b2015-05-11 10:17:43 +0200170 sequence_number_fir_(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000171
Erik Språng242e22b2015-05-11 10:17:43 +0200172 remb_bitrate_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000173
danilchap2b616392016-08-18 06:17:42 -0700174 tmmbr_send_bps_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200175 packet_oh_send_(0),
nisse284542b2017-01-10 08:58:32 -0800176 max_packet_size_(IP_PACKET_SIZE - 28), // IPv4 + UDP by default.
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000177
Erik Språng242e22b2015-05-11 10:17:43 +0200178 app_sub_type_(0),
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200179 app_name_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200180 app_data_(nullptr),
181 app_length_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000182
Erik Språng242e22b2015-05-11 10:17:43 +0200183 xr_send_receiver_reference_time_enabled_(false),
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000184 packet_type_counter_observer_(packet_type_counter_observer) {
sprang86fd9ed2015-09-29 04:45:43 -0700185 RTC_DCHECK(transport_ != nullptr);
Erik Språng242e22b2015-05-11 10:17:43 +0200186
187 builders_[kRtcpSr] = &RTCPSender::BuildSR;
188 builders_[kRtcpRr] = &RTCPSender::BuildRR;
Erik Språng0ea42d32015-06-25 14:46:16 +0200189 builders_[kRtcpSdes] = &RTCPSender::BuildSDES;
Erik Språng242e22b2015-05-11 10:17:43 +0200190 builders_[kRtcpPli] = &RTCPSender::BuildPLI;
191 builders_[kRtcpFir] = &RTCPSender::BuildFIR;
192 builders_[kRtcpSli] = &RTCPSender::BuildSLI;
193 builders_[kRtcpRpsi] = &RTCPSender::BuildRPSI;
194 builders_[kRtcpRemb] = &RTCPSender::BuildREMB;
195 builders_[kRtcpBye] = &RTCPSender::BuildBYE;
196 builders_[kRtcpApp] = &RTCPSender::BuildAPP;
197 builders_[kRtcpTmmbr] = &RTCPSender::BuildTMMBR;
198 builders_[kRtcpTmmbn] = &RTCPSender::BuildTMMBN;
199 builders_[kRtcpNack] = &RTCPSender::BuildNACK;
sprang5e38c962016-12-01 05:18:09 -0800200 builders_[kRtcpAnyExtendedReports] = &RTCPSender::BuildExtendedReports;
niklase@google.com470e71d2011-07-07 08:21:25 +0000201}
202
danilchap162abd32015-12-10 02:39:40 -0800203RTCPSender::~RTCPSender() {}
niklase@google.com470e71d2011-07-07 08:21:25 +0000204
pbosda903ea2015-10-02 02:36:56 -0700205RtcpMode RTCPSender::Status() const {
danilchap56036ff2016-03-22 11:14:09 -0700206 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200207 return method_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000208}
209
skvlad1c392cc2016-04-01 14:46:44 -0700210void RTCPSender::SetRTCPStatus(RtcpMode new_method) {
danilchap56036ff2016-03-22 11:14:09 -0700211 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000212
skvlad1c392cc2016-04-01 14:46:44 -0700213 if (method_ == RtcpMode::kOff && new_method != RtcpMode::kOff) {
214 // When switching on, reschedule the next packet
215 next_time_to_send_rtcp_ =
Erik Språng242e22b2015-05-11 10:17:43 +0200216 clock_->TimeInMilliseconds() +
217 (audio_ ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
skvlad1c392cc2016-04-01 14:46:44 -0700218 }
219 method_ = new_method;
niklase@google.com470e71d2011-07-07 08:21:25 +0000220}
221
Erik Språng61be2a42015-04-27 13:32:52 +0200222bool RTCPSender::Sending() const {
danilchap56036ff2016-03-22 11:14:09 -0700223 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200224 return sending_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000225}
226
Erik Språng61be2a42015-04-27 13:32:52 +0200227int32_t RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
228 bool sending) {
229 bool sendRTCPBye = false;
230 {
danilchap56036ff2016-03-22 11:14:09 -0700231 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000232
pbosda903ea2015-10-02 02:36:56 -0700233 if (method_ != RtcpMode::kOff) {
Erik Språng242e22b2015-05-11 10:17:43 +0200234 if (sending == false && sending_ == true) {
Erik Språng61be2a42015-04-27 13:32:52 +0200235 // Trigger RTCP bye
236 sendRTCPBye = true;
237 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000238 }
Erik Språng242e22b2015-05-11 10:17:43 +0200239 sending_ = sending;
Erik Språng61be2a42015-04-27 13:32:52 +0200240 }
241 if (sendRTCPBye)
242 return SendRTCP(feedback_state, kRtcpBye);
243 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000244}
245
Erik Språng61be2a42015-04-27 13:32:52 +0200246bool RTCPSender::REMB() const {
danilchap56036ff2016-03-22 11:14:09 -0700247 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200248 return remb_enabled_;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000249}
250
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000251void RTCPSender::SetREMBStatus(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700252 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200253 remb_enabled_ = enable;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000254}
255
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000256void RTCPSender::SetREMBData(uint32_t bitrate,
257 const std::vector<uint32_t>& ssrcs) {
danilchap56036ff2016-03-22 11:14:09 -0700258 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200259 remb_bitrate_ = bitrate;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000260 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000261
Erik Språng242e22b2015-05-11 10:17:43 +0200262 if (remb_enabled_)
263 SetFlag(kRtcpRemb, false);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000264 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
265 // throttled by the caller.
Erik Språng242e22b2015-05-11 10:17:43 +0200266 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000267}
268
Erik Språng61be2a42015-04-27 13:32:52 +0200269bool RTCPSender::TMMBR() const {
danilchap56036ff2016-03-22 11:14:09 -0700270 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200271 return IsFlagPresent(RTCPPacketType::kRtcpTmmbr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000272}
273
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000274void RTCPSender::SetTMMBRStatus(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700275 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200276 if (enable) {
277 SetFlag(RTCPPacketType::kRtcpTmmbr, false);
278 } else {
279 ConsumeFlag(RTCPPacketType::kRtcpTmmbr, true);
280 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000281}
282
nisse284542b2017-01-10 08:58:32 -0800283void RTCPSender::SetMaxRtpPacketSize(size_t max_packet_size) {
284 max_packet_size_ = max_packet_size;
danilchap41befce2016-03-30 11:11:51 -0700285}
286
danilchap71fead22016-08-18 02:01:49 -0700287void RTCPSender::SetTimestampOffset(uint32_t timestamp_offset) {
danilchap56036ff2016-03-22 11:14:09 -0700288 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap71fead22016-08-18 02:01:49 -0700289 timestamp_offset_ = timestamp_offset;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000290}
291
292void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
293 int64_t capture_time_ms) {
danilchap56036ff2016-03-22 11:14:09 -0700294 rtc::CritScope lock(&critical_section_rtcp_sender_);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000295 last_rtp_timestamp_ = rtp_timestamp;
296 if (capture_time_ms < 0) {
297 // We don't currently get a capture time from VoiceEngine.
Erik Språng242e22b2015-05-11 10:17:43 +0200298 last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000299 } else {
300 last_frame_capture_time_ms_ = capture_time_ms;
301 }
302}
303
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000304void RTCPSender::SetSSRC(uint32_t ssrc) {
danilchap56036ff2016-03-22 11:14:09 -0700305 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000306
Erik Språng242e22b2015-05-11 10:17:43 +0200307 if (ssrc_ != 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200308 // not first SetSSRC, probably due to a collision
309 // schedule a new RTCP report
310 // make sure that we send a RTP packet
Erik Språng242e22b2015-05-11 10:17:43 +0200311 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
Erik Språng61be2a42015-04-27 13:32:52 +0200312 }
Erik Språng242e22b2015-05-11 10:17:43 +0200313 ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000314}
315
Erik Språng61be2a42015-04-27 13:32:52 +0200316void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
danilchap56036ff2016-03-22 11:14:09 -0700317 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200318 remote_ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000319}
320
Peter Boström9ba52f82015-06-01 14:12:28 +0200321int32_t RTCPSender::SetCNAME(const char* c_name) {
322 if (!c_name)
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000323 return -1;
324
kwiberg352444f2016-11-28 15:58:53 -0800325 RTC_DCHECK_LT(strlen(c_name), RTCP_CNAME_SIZE);
danilchap56036ff2016-03-22 11:14:09 -0700326 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200327 cname_ = c_name;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000328 return 0;
329}
330
Erik Språng0ea42d32015-06-25 14:46:16 +0200331int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC, const char* c_name) {
danilchap56036ff2016-03-22 11:14:09 -0700332 RTC_DCHECK(c_name);
kwiberg352444f2016-11-28 15:58:53 -0800333 RTC_DCHECK_LT(strlen(c_name), RTCP_CNAME_SIZE);
danilchap56036ff2016-03-22 11:14:09 -0700334 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200335 if (csrc_cnames_.size() >= kRtpCsrcSize)
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000336 return -1;
Erik Språng0ea42d32015-06-25 14:46:16 +0200337
338 csrc_cnames_[SSRC] = c_name;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000339 return 0;
340}
341
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000342int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
danilchap56036ff2016-03-22 11:14:09 -0700343 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200344 auto it = csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000345
Erik Språng242e22b2015-05-11 10:17:43 +0200346 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000347 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200348
Erik Språng242e22b2015-05-11 10:17:43 +0200349 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000350 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000351}
352
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000353bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
danilchap162abd32015-12-10 02:39:40 -0800354 /*
355 For audio we use a fix 5 sec interval
niklase@google.com470e71d2011-07-07 08:21:25 +0000356
danilchap162abd32015-12-10 02:39:40 -0800357 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
358 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
359 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000360
361
danilchap162abd32015-12-10 02:39:40 -0800362 From RFC 3550
niklase@google.com470e71d2011-07-07 08:21:25 +0000363
danilchap162abd32015-12-10 02:39:40 -0800364 MAX RTCP BW is 5% if the session BW
365 A send report is approximately 65 bytes inc CNAME
366 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000367
danilchap162abd32015-12-10 02:39:40 -0800368 The RECOMMENDED value for the reduced minimum in seconds is 360
369 divided by the session bandwidth in kilobits/second. This minimum
370 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
niklase@google.com470e71d2011-07-07 08:21:25 +0000371
danilchap162abd32015-12-10 02:39:40 -0800372 If the participant has not yet sent an RTCP packet (the variable
373 initial is true), the constant Tmin is set to 2.5 seconds, else it
374 is set to 5 seconds.
niklase@google.com470e71d2011-07-07 08:21:25 +0000375
danilchap162abd32015-12-10 02:39:40 -0800376 The interval between RTCP packets is varied randomly over the
377 range [0.5,1.5] times the calculated interval to avoid unintended
378 synchronization of all participants
niklase@google.com470e71d2011-07-07 08:21:25 +0000379
danilchap162abd32015-12-10 02:39:40 -0800380 if we send
381 If the participant is a sender (we_sent true), the constant C is
382 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
383 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
384 number of senders.
niklase@google.com470e71d2011-07-07 08:21:25 +0000385
danilchap162abd32015-12-10 02:39:40 -0800386 if we receive only
387 If we_sent is not true, the constant C is set
388 to the average RTCP packet size divided by 75% of the RTCP
389 bandwidth. The constant n is set to the number of receivers
390 (members - senders). If the number of senders is greater than
391 25%, senders and receivers are treated together.
niklase@google.com470e71d2011-07-07 08:21:25 +0000392
danilchap162abd32015-12-10 02:39:40 -0800393 reconsideration NOT required for peer-to-peer
394 "timer reconsideration" is
395 employed. This algorithm implements a simple back-off mechanism
396 which causes users to hold back RTCP packet transmission if the
397 group sizes are increasing.
niklase@google.com470e71d2011-07-07 08:21:25 +0000398
danilchap162abd32015-12-10 02:39:40 -0800399 n = number of members
400 C = avg_size/(rtcpBW/4)
niklase@google.com470e71d2011-07-07 08:21:25 +0000401
danilchap162abd32015-12-10 02:39:40 -0800402 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
niklase@google.com470e71d2011-07-07 08:21:25 +0000403
danilchap162abd32015-12-10 02:39:40 -0800404 4. The calculated interval T is set to a number uniformly distributed
405 between 0.5 and 1.5 times the deterministic calculated interval.
niklase@google.com470e71d2011-07-07 08:21:25 +0000406
danilchap162abd32015-12-10 02:39:40 -0800407 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
408 for the fact that the timer reconsideration algorithm converges to
409 a value of the RTCP bandwidth below the intended average
410 */
niklase@google.com470e71d2011-07-07 08:21:25 +0000411
Erik Språng242e22b2015-05-11 10:17:43 +0200412 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000413
danilchap56036ff2016-03-22 11:14:09 -0700414 rtc::CritScope lock(&critical_section_rtcp_sender_);
xians@webrtc.org8738d272011-11-25 13:43:53 +0000415
pbosda903ea2015-10-02 02:36:56 -0700416 if (method_ == RtcpMode::kOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000417 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000418
Erik Språng242e22b2015-05-11 10:17:43 +0200419 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200420 // for video key-frames we want to send the RTCP before the large key-frame
421 // if we have a 100 ms margin
422 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
423 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000424
Erik Språng242e22b2015-05-11 10:17:43 +0200425 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200426 return true;
427 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200428 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200429 // wrap
430 return true;
431 }
432 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000433}
434
danilchap56036ff2016-03-22 11:14:09 -0700435std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSR(const RtcpContext& ctx) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200436 // Timestamp shouldn't be estimated before first media frame.
437 RTC_DCHECK_GE(last_frame_capture_time_ms_, 0);
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.
solenbergb19d2882016-10-03 06:22:25 -0700442 uint32_t rtp_rate =
443 (audio_ ? kBogusRtpRateForAudioRtcp : kVideoPayloadTypeFrequency) / 1000;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200444 uint32_t rtp_timestamp =
danilchap71fead22016-08-18 02:01:49 -0700445 timestamp_offset_ + last_rtp_timestamp_ +
solenbergb19d2882016-10-03 06:22:25 -0700446 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) * rtp_rate;
niklase@google.com470e71d2011-07-07 08:21:25 +0000447
Erik Språngf7c57762015-12-04 10:40:35 +0100448 rtcp::SenderReport* report = new rtcp::SenderReport();
danilchap822a16f2016-09-27 09:27:47 -0700449 report->SetSenderSsrc(ssrc_);
danilchap51813b32016-12-16 02:44:36 -0800450 report->SetNtp(ctx.now_);
danilchap822a16f2016-09-27 09:27:47 -0700451 report->SetRtpTimestamp(rtp_timestamp);
452 report->SetPacketCount(ctx.feedback_state_.packets_sent);
453 report->SetOctetCount(ctx.feedback_state_.media_bytes_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000454
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200455 for (auto it : report_blocks_)
danilchap822a16f2016-09-27 09:27:47 -0700456 report->AddReportBlock(it.second);
niklase@google.com470e71d2011-07-07 08:21:25 +0000457
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200458 report_blocks_.clear();
Erik Språngf7c57762015-12-04 10:40:35 +0100459
danilchap56036ff2016-03-22 11:14:09 -0700460 return std::unique_ptr<rtcp::RtcpPacket>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000461}
462
danilchap56036ff2016-03-22 11:14:09 -0700463std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSDES(
Erik Språngf7c57762015-12-04 10:40:35 +0100464 const RtcpContext& ctx) {
Erik Språng0ea42d32015-06-25 14:46:16 +0200465 size_t length_cname = cname_.length();
kwiberg352444f2016-11-28 15:58:53 -0800466 RTC_CHECK_LT(length_cname, RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000467
Erik Språngf7c57762015-12-04 10:40:35 +0100468 rtcp::Sdes* sdes = new rtcp::Sdes();
danilchap822a16f2016-09-27 09:27:47 -0700469 sdes->AddCName(ssrc_, cname_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200470
471 for (const auto it : csrc_cnames_)
danilchap822a16f2016-09-27 09:27:47 -0700472 sdes->AddCName(it.first, it.second);
Erik Språng0ea42d32015-06-25 14:46:16 +0200473
danilchap56036ff2016-03-22 11:14:09 -0700474 return std::unique_ptr<rtcp::RtcpPacket>(sdes);
niklase@google.com470e71d2011-07-07 08:21:25 +0000475}
476
danilchap56036ff2016-03-22 11:14:09 -0700477std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildRR(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100478 rtcp::ReceiverReport* report = new rtcp::ReceiverReport();
danilchap822a16f2016-09-27 09:27:47 -0700479 report->SetSenderSsrc(ssrc_);
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200480 for (auto it : report_blocks_)
danilchap822a16f2016-09-27 09:27:47 -0700481 report->AddReportBlock(it.second);
Erik Språng61be2a42015-04-27 13:32:52 +0200482
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200483 report_blocks_.clear();
danilchap56036ff2016-03-22 11:14:09 -0700484 return std::unique_ptr<rtcp::RtcpPacket>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000485}
486
danilchap56036ff2016-03-22 11:14:09 -0700487std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildPLI(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100488 rtcp::Pli* pli = new rtcp::Pli();
danilchap822a16f2016-09-27 09:27:47 -0700489 pli->SetSenderSsrc(ssrc_);
490 pli->SetMediaSsrc(remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200491
Erik Språng242e22b2015-05-11 10:17:43 +0200492 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
493 "RTCPSender::PLI");
494 ++packet_type_counter_.pli_packets;
495 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
496 ssrc_, packet_type_counter_.pli_packets);
497
danilchap56036ff2016-03-22 11:14:09 -0700498 return std::unique_ptr<rtcp::RtcpPacket>(pli);
Erik Språng61be2a42015-04-27 13:32:52 +0200499}
500
danilchap56036ff2016-03-22 11:14:09 -0700501std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildFIR(const RtcpContext& ctx) {
danilchap498ee8e2017-02-08 05:24:31 -0800502 ++sequence_number_fir_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000503
Erik Språngf7c57762015-12-04 10:40:35 +0100504 rtcp::Fir* fir = new rtcp::Fir();
danilchap822a16f2016-09-27 09:27:47 -0700505 fir->SetSenderSsrc(ssrc_);
506 fir->AddRequestTo(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();
danilchap822a16f2016-09-27 09:27:47 -0700526 sli->SetSenderSsrc(ssrc_);
527 sli->SetMediaSsrc(remote_ssrc_);
sprang0365a272015-08-11 01:02:37 -0700528 // Crop picture id to 6 least significant bits.
danilchap822a16f2016-09-27 09:27:47 -0700529 sli->AddPictureId(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();
danilchap822a16f2016-09-27 09:27:47 -0700552 rpsi->SetSenderSsrc(ssrc_);
553 rpsi->SetMediaSsrc(remote_ssrc_);
554 rpsi->SetPayloadType(ctx.feedback_state_.send_payload_type);
555 rpsi->SetPictureId(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();
danilchap822a16f2016-09-27 09:27:47 -0700563 remb->SetSenderSsrc(ssrc_);
564 remb->SetBitrateBps(remb_bitrate_);
565 remb->SetSsrcs(remb_ssrcs_);
Erik Språng61be2a42015-04-27 13:32:52 +0200566
Erik Språng242e22b2015-05-11 10:17:43 +0200567 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
568 "RTCPSender::REMB");
569
danilchap56036ff2016-03-22 11:14:09 -0700570 return std::unique_ptr<rtcp::RtcpPacket>(remb);
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000571}
572
Erik Språng61be2a42015-04-27 13:32:52 +0200573void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
danilchap56036ff2016-03-22 11:14:09 -0700574 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap2b616392016-08-18 06:17:42 -0700575 tmmbr_send_bps_ = target_bitrate;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000576}
577
danilchap56036ff2016-03-22 11:14:09 -0700578std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBR(
Erik Språngf7c57762015-12-04 10:40:35 +0100579 const RtcpContext& ctx) {
580 if (ctx.feedback_state_.module == nullptr)
581 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200582 // Before sending the TMMBR check the received TMMBN, only an owner is
583 // allowed to raise the bitrate:
584 // * If the sender is an owner of the TMMBN -> send TMMBR
585 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000586
Erik Språng61be2a42015-04-27 13:32:52 +0200587 // get current bounding set from RTCP receiver
danilchap2b616392016-08-18 06:17:42 -0700588 bool tmmbr_owner = false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000589
Erik Språng242e22b2015-05-11 10:17:43 +0200590 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
591 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
Erik Språng61be2a42015-04-27 13:32:52 +0200592 // since RTCPreceiver is not doing the reverse we should be fine
danilchap2b616392016-08-18 06:17:42 -0700593 std::vector<rtcp::TmmbItem> candidates =
594 ctx.feedback_state_.module->BoundingSet(&tmmbr_owner);
niklase@google.com470e71d2011-07-07 08:21:25 +0000595
danilchap2b616392016-08-18 06:17:42 -0700596 if (!candidates.empty()) {
597 for (const auto& candidate : candidates) {
598 if (candidate.bitrate_bps() == tmmbr_send_bps_ &&
599 candidate.packet_overhead() == packet_oh_send_) {
Erik Språngf7c57762015-12-04 10:40:35 +0100600 // Do not send the same tuple.
601 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200602 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000603 }
danilchap2b616392016-08-18 06:17:42 -0700604 if (!tmmbr_owner) {
605 // Use received bounding set as candidate set.
606 // Add current tuple.
607 candidates.emplace_back(ssrc_, tmmbr_send_bps_, packet_oh_send_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000608
danilchap2b616392016-08-18 06:17:42 -0700609 // Find bounding set.
danilchap2f69ce92016-08-16 03:21:38 -0700610 std::vector<rtcp::TmmbItem> bounding =
611 TMMBRHelp::FindBoundingSet(std::move(candidates));
danilchap2b616392016-08-18 06:17:42 -0700612 tmmbr_owner = TMMBRHelp::IsOwner(bounding, ssrc_);
613 if (!tmmbr_owner) {
Erik Språngf7c57762015-12-04 10:40:35 +0100614 // Did not enter bounding set, no meaning to send this request.
615 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200616 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000617 }
Erik Språng61be2a42015-04-27 13:32:52 +0200618 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000619
danilchap2b616392016-08-18 06:17:42 -0700620 if (!tmmbr_send_bps_)
Erik Språngf7c57762015-12-04 10:40:35 +0100621 return nullptr;
sprang81a3e602015-08-21 05:30:11 -0700622
Erik Språngf7c57762015-12-04 10:40:35 +0100623 rtcp::Tmmbr* tmmbr = new rtcp::Tmmbr();
danilchap822a16f2016-09-27 09:27:47 -0700624 tmmbr->SetSenderSsrc(ssrc_);
danilchapf174e3a2016-02-05 04:56:36 -0800625 rtcp::TmmbItem request;
626 request.set_ssrc(remote_ssrc_);
danilchap2b616392016-08-18 06:17:42 -0700627 request.set_bitrate_bps(tmmbr_send_bps_);
danilchapf174e3a2016-02-05 04:56:36 -0800628 request.set_packet_overhead(packet_oh_send_);
danilchap822a16f2016-09-27 09:27:47 -0700629 tmmbr->AddTmmbr(request);
Erik Språngf7c57762015-12-04 10:40:35 +0100630
danilchap56036ff2016-03-22 11:14:09 -0700631 return std::unique_ptr<rtcp::RtcpPacket>(tmmbr);
Erik Språng61be2a42015-04-27 13:32:52 +0200632}
633
danilchap56036ff2016-03-22 11:14:09 -0700634std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBN(
Erik Språngf7c57762015-12-04 10:40:35 +0100635 const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100636 rtcp::Tmmbn* tmmbn = new rtcp::Tmmbn();
danilchap822a16f2016-09-27 09:27:47 -0700637 tmmbn->SetSenderSsrc(ssrc_);
danilchap6eaa3a42016-05-09 10:59:50 -0700638 for (const rtcp::TmmbItem& tmmbr : tmmbn_to_send_) {
639 if (tmmbr.bitrate_bps() > 0) {
danilchap822a16f2016-09-27 09:27:47 -0700640 tmmbn->AddTmmbr(tmmbr);
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000641 }
Erik Språng61be2a42015-04-27 13:32:52 +0200642 }
sprangd83df502015-08-27 01:05:08 -0700643
danilchap56036ff2016-03-22 11:14:09 -0700644 return std::unique_ptr<rtcp::RtcpPacket>(tmmbn);
niklase@google.com470e71d2011-07-07 08:21:25 +0000645}
646
danilchap56036ff2016-03-22 11:14:09 -0700647std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildAPP(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100648 rtcp::App* app = new rtcp::App();
danilchap822a16f2016-09-27 09:27:47 -0700649 app->SetSsrc(ssrc_);
650 app->SetSubType(app_sub_type_);
651 app->SetName(app_name_);
652 app->SetData(app_data_.get(), app_length_);
Erik Språng521875a2015-09-01 10:11:16 +0200653
danilchap56036ff2016-03-22 11:14:09 -0700654 return std::unique_ptr<rtcp::RtcpPacket>(app);
Erik Språng61be2a42015-04-27 13:32:52 +0200655}
656
danilchap56036ff2016-03-22 11:14:09 -0700657std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildNACK(
Erik Språngf7c57762015-12-04 10:40:35 +0100658 const RtcpContext& ctx) {
659 rtcp::Nack* nack = new rtcp::Nack();
danilchap822a16f2016-09-27 09:27:47 -0700660 nack->SetSenderSsrc(ssrc_);
661 nack->SetMediaSsrc(remote_ssrc_);
662 nack->SetPacketIds(ctx.nack_list_, ctx.nack_size_);
Erik Språng61be2a42015-04-27 13:32:52 +0200663
664 // Report stats.
665 NACKStringBuilder stringBuilder;
Erik Språngf7c57762015-12-04 10:40:35 +0100666 for (int idx = 0; idx < ctx.nack_size_; ++idx) {
667 stringBuilder.PushNACK(ctx.nack_list_[idx]);
668 nack_stats_.ReportRequest(ctx.nack_list_[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +0200669 }
Erik Språng61be2a42015-04-27 13:32:52 +0200670 packet_type_counter_.nack_requests = nack_stats_.requests();
671 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +0200672
673 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
674 "RTCPSender::NACK", "nacks",
675 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
676 ++packet_type_counter_.nack_packets;
677 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
678 ssrc_, packet_type_counter_.nack_packets);
679
danilchap56036ff2016-03-22 11:14:09 -0700680 return std::unique_ptr<rtcp::RtcpPacket>(nack);
Erik Språng61be2a42015-04-27 13:32:52 +0200681}
682
danilchap56036ff2016-03-22 11:14:09 -0700683std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildBYE(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100684 rtcp::Bye* bye = new rtcp::Bye();
danilchap822a16f2016-09-27 09:27:47 -0700685 bye->SetSenderSsrc(ssrc_);
686 bye->SetCsrcs(csrcs_);
sprangd8ee4f92015-08-24 03:25:19 -0700687
danilchap56036ff2016-03-22 11:14:09 -0700688 return std::unique_ptr<rtcp::RtcpPacket>(bye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000689}
690
sprang5e38c962016-12-01 05:18:09 -0800691std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildExtendedReports(
Erik Språngf7c57762015-12-04 10:40:35 +0100692 const RtcpContext& ctx) {
sprang5e38c962016-12-01 05:18:09 -0800693 std::unique_ptr<rtcp::ExtendedReports> xr(new rtcp::ExtendedReports());
danilchap822a16f2016-09-27 09:27:47 -0700694 xr->SetSenderSsrc(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000695
sprang5e38c962016-12-01 05:18:09 -0800696 if (!sending_ && xr_send_receiver_reference_time_enabled_) {
697 rtcp::Rrtr rrtr;
danilchap51813b32016-12-16 02:44:36 -0800698 rrtr.SetNtp(ctx.now_);
sprang5e38c962016-12-01 05:18:09 -0800699 xr->SetRrtr(rrtr);
700 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000701
sprang5e38c962016-12-01 05:18:09 -0800702 if (ctx.feedback_state_.has_last_xr_rr) {
703 xr->AddDlrrItem(ctx.feedback_state_.last_xr_rr);
704 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000705
sprang5e38c962016-12-01 05:18:09 -0800706 if (video_bitrate_allocation_) {
707 rtcp::TargetBitrate target_bitrate;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000708
sprang5e38c962016-12-01 05:18:09 -0800709 for (int sl = 0; sl < kMaxSpatialLayers; ++sl) {
710 for (int tl = 0; tl < kMaxTemporalStreams; ++tl) {
711 uint32_t layer_bitrate_bps =
712 video_bitrate_allocation_->GetBitrate(sl, tl);
713 if (layer_bitrate_bps > 0)
714 target_bitrate.AddTargetBitrate(sl, tl, layer_bitrate_bps / 1000);
715 }
716 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000717
sprang5e38c962016-12-01 05:18:09 -0800718 xr->SetTargetBitrate(target_bitrate);
719 video_bitrate_allocation_.reset();
720 }
Erik Språngca28fdc2015-08-31 14:00:50 +0200721
sprang5e38c962016-12-01 05:18:09 -0800722 if (xr_voip_metric_) {
723 rtcp::VoipMetric voip;
724 voip.SetMediaSsrc(remote_ssrc_);
725 voip.SetVoipMetric(*xr_voip_metric_);
726 xr_voip_metric_.reset();
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000727
sprang5e38c962016-12-01 05:18:09 -0800728 xr->SetVoipMetric(voip);
729 }
Erik Språngca28fdc2015-08-31 14:00:50 +0200730
sprang5e38c962016-12-01 05:18:09 -0800731 return std::move(xr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000732}
733
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000734int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200735 RTCPPacketType packetType,
736 int32_t nack_size,
737 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000738 uint64_t pictureID) {
Erik Språng242e22b2015-05-11 10:17:43 +0200739 return SendCompoundRTCP(
740 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
danilchap498ee8e2017-02-08 05:24:31 -0800741 nack_size, nack_list, pictureID);
Erik Språng242e22b2015-05-11 10:17:43 +0200742}
743
744int32_t RTCPSender::SendCompoundRTCP(
745 const FeedbackState& feedback_state,
Erik Språngf7c57762015-12-04 10:40:35 +0100746 const std::set<RTCPPacketType>& packet_types,
Erik Språng242e22b2015-05-11 10:17:43 +0200747 int32_t nack_size,
748 const uint16_t* nack_list,
Erik Språng242e22b2015-05-11 10:17:43 +0200749 uint64_t pictureID) {
terelius429c3452016-01-21 05:42:04 -0800750 PacketContainer container(transport_, event_log_);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000751 {
danilchap56036ff2016-03-22 11:14:09 -0700752 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbosda903ea2015-10-02 02:36:56 -0700753 if (method_ == RtcpMode::kOff) {
Erik Språng61be2a42015-04-27 13:32:52 +0200754 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
755 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +0000756 }
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200757 // Add all flags as volatile. Non volatile entries will not be overwritten.
758 // All new volatile flags added will be consumed by the end of this call.
759 SetFlags(packet_types, true);
760
761 // Prevent sending streams to send SR before any media has been sent.
762 const bool can_calculate_rtp_timestamp = (last_frame_capture_time_ms_ >= 0);
763 if (!can_calculate_rtp_timestamp) {
764 bool consumed_sr_flag = ConsumeFlag(kRtcpSr);
765 bool consumed_report_flag = sending_ && ConsumeFlag(kRtcpReport);
766 bool sender_report = consumed_report_flag || consumed_sr_flag;
767 if (sender_report && AllVolatileFlagsConsumed()) {
768 // This call was for Sender Report and nothing else.
769 return 0;
770 }
771 if (sending_ && method_ == RtcpMode::kCompound) {
772 // Not allowed to send any RTCP packet without sender report.
773 return -1;
774 }
775 }
776
777 if (packet_type_counter_.first_packet_time_ms == -1)
778 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språngf7c57762015-12-04 10:40:35 +0100779
780 // We need to send our NTP even if we haven't received any reports.
danilchap498ee8e2017-02-08 05:24:31 -0800781 RtcpContext context(feedback_state, nack_size, nack_list, pictureID,
danilchap37953762017-02-09 11:15:25 -0800782 clock_->CurrentNtpTime());
Erik Språngf7c57762015-12-04 10:40:35 +0100783
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200784 PrepareReport(feedback_state);
Erik Språngf7c57762015-12-04 10:40:35 +0100785
danilchap56036ff2016-03-22 11:14:09 -0700786 std::unique_ptr<rtcp::RtcpPacket> packet_bye;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800787
Erik Språngf7c57762015-12-04 10:40:35 +0100788 auto it = report_flags_.begin();
789 while (it != report_flags_.end()) {
790 auto builder_it = builders_.find(it->type);
sprang5e38c962016-12-01 05:18:09 -0800791 RTC_DCHECK(builder_it != builders_.end())
792 << "Could not find builder for packet type " << it->type;
Erik Språngf7c57762015-12-04 10:40:35 +0100793 if (it->is_volatile) {
794 report_flags_.erase(it++);
795 } else {
796 ++it;
797 }
798
799 BuilderFunc func = builder_it->second;
danilchap56036ff2016-03-22 11:14:09 -0700800 std::unique_ptr<rtcp::RtcpPacket> packet = (this->*func)(context);
Erik Språngf7c57762015-12-04 10:40:35 +0100801 if (packet.get() == nullptr)
802 return -1;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800803 // If there is a BYE, don't append now - save it and append it
804 // at the end later.
805 if (builder_it->first == kRtcpBye) {
806 packet_bye = std::move(packet);
807 } else {
808 container.Append(packet.release());
809 }
810 }
811
812 // Append the BYE now at the end
813 if (packet_bye) {
814 container.Append(packet_bye.release());
Erik Språngf7c57762015-12-04 10:40:35 +0100815 }
816
817 if (packet_type_counter_observer_ != nullptr) {
818 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
819 remote_ssrc_, packet_type_counter_);
820 }
821
822 RTC_DCHECK(AllVolatileFlagsConsumed());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000823 }
Erik Språng61be2a42015-04-27 13:32:52 +0200824
nisse284542b2017-01-10 08:58:32 -0800825 size_t bytes_sent = container.SendPackets(max_packet_size_);
Erik Språngf7c57762015-12-04 10:40:35 +0100826 return bytes_sent == 0 ? -1 : 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000827}
828
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200829void RTCPSender::PrepareReport(const FeedbackState& feedback_state) {
Erik Språng242e22b2015-05-11 10:17:43 +0200830 bool generate_report;
831 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
832 // Report type already explicitly set, don't automatically populate.
833 generate_report = true;
henrikg91d6ede2015-09-17 00:24:34 -0700834 RTC_DCHECK(ConsumeFlag(kRtcpReport) == false);
Erik Språng242e22b2015-05-11 10:17:43 +0200835 } else {
836 generate_report =
pbosda903ea2015-10-02 02:36:56 -0700837 (ConsumeFlag(kRtcpReport) && method_ == RtcpMode::kReducedSize) ||
838 method_ == RtcpMode::kCompound;
Erik Språng242e22b2015-05-11 10:17:43 +0200839 if (generate_report)
840 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000841 }
842
Erik Språng0ea42d32015-06-25 14:46:16 +0200843 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
Erik Språng242e22b2015-05-11 10:17:43 +0200844 SetFlag(kRtcpSdes, true);
845
Erik Språng242e22b2015-05-11 10:17:43 +0200846 if (generate_report) {
sprang5e38c962016-12-01 05:18:09 -0800847 if ((!sending_ && xr_send_receiver_reference_time_enabled_) ||
848 feedback_state.has_last_xr_rr || video_bitrate_allocation_) {
849 SetFlag(kRtcpAnyExtendedReports, true);
850 }
Erik Språng242e22b2015-05-11 10:17:43 +0200851
852 // generate next time to send an RTCP report
danilchap47a740b2015-12-15 00:30:07 -0800853 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000854
danilchap47a740b2015-12-15 00:30:07 -0800855 if (!audio_) {
Erik Språng242e22b2015-05-11 10:17:43 +0200856 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200857 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
858 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
859 if (send_bitrate_kbit != 0)
860 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000861 }
Erik Språng61be2a42015-04-27 13:32:52 +0200862 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
863 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
Erik Språng61be2a42015-04-27 13:32:52 +0200864 }
danilchap47a740b2015-12-15 00:30:07 -0800865 // The interval between RTCP packets is varied randomly over the
866 // range [1/2,3/2] times the calculated interval.
867 uint32_t timeToNext =
868 random_.Rand(minIntervalMs * 1 / 2, minIntervalMs * 3 / 2);
Erik Språng242e22b2015-05-11 10:17:43 +0200869 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000870
Per83d09102016-04-15 14:59:13 +0200871 if (receive_statistics_) {
872 StatisticianMap statisticians =
873 receive_statistics_->GetActiveStatisticians();
874 RTC_DCHECK(report_blocks_.empty());
875 for (auto& it : statisticians) {
876 AddReportBlock(feedback_state, it.first, it.second);
877 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000878 }
879 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000880}
881
danilchapa72e7342015-12-22 08:07:45 -0800882bool RTCPSender::AddReportBlock(const FeedbackState& feedback_state,
883 uint32_t ssrc,
884 StreamStatistician* statistician) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000885 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000886 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000887 if (!statistician->GetStatistics(&stats, true))
888 return false;
danilchapa72e7342015-12-22 08:07:45 -0800889
890 if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) {
891 LOG(LS_WARNING) << "Too many report blocks.";
892 return false;
893 }
894 RTC_DCHECK(report_blocks_.find(ssrc) == report_blocks_.end());
895 rtcp::ReportBlock* block = &report_blocks_[ssrc];
danilchap822a16f2016-09-27 09:27:47 -0700896 block->SetMediaSsrc(ssrc);
897 block->SetFractionLost(stats.fraction_lost);
898 if (!block->SetCumulativeLost(stats.cumulative_lost)) {
danilchapa72e7342015-12-22 08:07:45 -0800899 report_blocks_.erase(ssrc);
900 LOG(LS_WARNING) << "Cumulative lost is oversized.";
901 return false;
902 }
danilchap822a16f2016-09-27 09:27:47 -0700903 block->SetExtHighestSeqNum(stats.extended_max_sequence_number);
904 block->SetJitter(stats.jitter);
905 block->SetLastSr(feedback_state.remote_sr);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000906
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200907 // TODO(sprang): Do we really need separate time stamps for each report?
908 // Get our NTP as late as possible to avoid a race.
909 uint32_t ntp_secs;
910 uint32_t ntp_frac;
911 clock_->CurrentNtp(ntp_secs, ntp_frac);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000912
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200913 // Delay since last received report.
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000914 if ((feedback_state.last_rr_ntp_secs != 0) ||
915 (feedback_state.last_rr_ntp_frac != 0)) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200916 // Get the 16 lowest bits of seconds and the 16 highest bits of fractions.
917 uint32_t now = ntp_secs & 0x0000FFFF;
Erik Språng61be2a42015-04-27 13:32:52 +0200918 now <<= 16;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200919 now += (ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000920
Erik Språng61be2a42015-04-27 13:32:52 +0200921 uint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
922 receiveTime <<= 16;
923 receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000924
danilchap822a16f2016-09-27 09:27:47 -0700925 block->SetDelayLastSr(now - receiveTime);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000926 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000927 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000928}
929
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000930void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
kwiberg352444f2016-11-28 15:58:53 -0800931 RTC_DCHECK_LE(csrcs.size(), kRtpCsrcSize);
danilchap56036ff2016-03-22 11:14:09 -0700932 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000933 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +0000934}
935
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000936int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
937 uint32_t name,
938 const uint8_t* data,
939 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +0200940 if (length % 4 != 0) {
941 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
942 return -1;
943 }
danilchap56036ff2016-03-22 11:14:09 -0700944 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000945
Erik Språng242e22b2015-05-11 10:17:43 +0200946 SetFlag(kRtcpApp, true);
947 app_sub_type_ = subType;
948 app_name_ = name;
949 app_data_.reset(new uint8_t[length]);
950 app_length_ = length;
951 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +0200952 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000953}
954
spranga790d832016-12-02 07:29:44 -0800955// TODO(sprang): Remove support for VoIP metrics? (Not used in receiver.)
Erik Språng61be2a42015-04-27 13:32:52 +0200956int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
danilchap56036ff2016-03-22 11:14:09 -0700957 rtc::CritScope lock(&critical_section_rtcp_sender_);
sprang5e38c962016-12-01 05:18:09 -0800958 xr_voip_metric_.emplace(*VoIPMetric);
niklase@google.com470e71d2011-07-07 08:21:25 +0000959
sprang5e38c962016-12-01 05:18:09 -0800960 SetFlag(kRtcpAnyExtendedReports, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200961 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000962}
963
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000964void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700965 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200966 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000967}
968
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000969bool RTCPSender::RtcpXrReceiverReferenceTime() const {
danilchap56036ff2016-03-22 11:14:09 -0700970 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200971 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000972}
973
danilchap853ecb22016-08-22 08:26:15 -0700974void RTCPSender::SetTmmbn(std::vector<rtcp::TmmbItem> bounding_set) {
danilchap56036ff2016-03-22 11:14:09 -0700975 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap853ecb22016-08-22 08:26:15 -0700976 tmmbn_to_send_ = std::move(bounding_set);
danilchap6eaa3a42016-05-09 10:59:50 -0700977 SetFlag(kRtcpTmmbn, true);
niklase@google.com470e71d2011-07-07 08:21:25 +0000978}
Erik Språng61be2a42015-04-27 13:32:52 +0200979
sprang5e38c962016-12-01 05:18:09 -0800980void RTCPSender::SetFlag(uint32_t type, bool is_volatile) {
981 if (type & kRtcpAnyExtendedReports) {
982 report_flags_.insert(ReportFlag(kRtcpAnyExtendedReports, is_volatile));
983 } else {
984 report_flags_.insert(ReportFlag(type, is_volatile));
985 }
Erik Språng242e22b2015-05-11 10:17:43 +0200986}
987
988void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
989 bool is_volatile) {
990 for (RTCPPacketType type : types)
991 SetFlag(type, is_volatile);
992}
993
sprang5e38c962016-12-01 05:18:09 -0800994bool RTCPSender::IsFlagPresent(uint32_t type) const {
Erik Språng242e22b2015-05-11 10:17:43 +0200995 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
996}
997
sprang5e38c962016-12-01 05:18:09 -0800998bool RTCPSender::ConsumeFlag(uint32_t type, bool forced) {
Erik Språng242e22b2015-05-11 10:17:43 +0200999 auto it = report_flags_.find(ReportFlag(type, false));
1000 if (it == report_flags_.end())
1001 return false;
1002 if (it->is_volatile || forced)
1003 report_flags_.erase((it));
1004 return true;
1005}
1006
1007bool RTCPSender::AllVolatileFlagsConsumed() const {
1008 for (const ReportFlag& flag : report_flags_) {
1009 if (flag.is_volatile)
1010 return false;
1011 }
1012 return true;
1013}
1014
sprang5e38c962016-12-01 05:18:09 -08001015void RTCPSender::SetVideoBitrateAllocation(const BitrateAllocation& bitrate) {
1016 rtc::CritScope lock(&critical_section_rtcp_sender_);
1017 video_bitrate_allocation_.emplace(bitrate);
1018 SetFlag(kRtcpAnyExtendedReports, true);
1019}
1020
sprang233bd872015-09-08 13:25:16 -07001021bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
sprang233bd872015-09-08 13:25:16 -07001022 class Sender : public rtcp::RtcpPacket::PacketReadyCallback {
1023 public:
terelius429c3452016-01-21 05:42:04 -08001024 Sender(Transport* transport, RtcEventLog* event_log)
1025 : transport_(transport), event_log_(event_log), send_failure_(false) {}
sprang233bd872015-09-08 13:25:16 -07001026
1027 void OnPacketReady(uint8_t* data, size_t length) override {
terelius429c3452016-01-21 05:42:04 -08001028 if (transport_->SendRtcp(data, length)) {
1029 if (event_log_) {
1030 event_log_->LogRtcpPacket(kOutgoingPacket, MediaType::ANY, data,
1031 length);
1032 }
1033 } else {
sprang233bd872015-09-08 13:25:16 -07001034 send_failure_ = true;
terelius429c3452016-01-21 05:42:04 -08001035 }
sprang233bd872015-09-08 13:25:16 -07001036 }
1037
1038 Transport* const transport_;
terelius429c3452016-01-21 05:42:04 -08001039 RtcEventLog* const event_log_;
sprang233bd872015-09-08 13:25:16 -07001040 bool send_failure_;
terelius429c3452016-01-21 05:42:04 -08001041 // TODO(terelius): We would like to
1042 // RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(Sender);
1043 // but we can't because of an incorrect warning (C4822) in MVS 2013.
1044 } sender(transport_, event_log_);
sprang233bd872015-09-08 13:25:16 -07001045
stefanb77c7162017-02-06 06:29:38 -08001046 {
1047 rtc::CritScope lock(&critical_section_rtcp_sender_);
1048 if (method_ == RtcpMode::kOff)
1049 return false;
1050 }
1051
nisse284542b2017-01-10 08:58:32 -08001052 RTC_DCHECK_LE(max_packet_size_, IP_PACKET_SIZE);
sprang233bd872015-09-08 13:25:16 -07001053 uint8_t buffer[IP_PACKET_SIZE];
nisse284542b2017-01-10 08:58:32 -08001054 return packet.BuildExternalBuffer(buffer, max_packet_size_, &sender) &&
sprang233bd872015-09-08 13:25:16 -07001055 !sender.send_failure_;
1056}
1057
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001058} // namespace webrtc