blob: 6d42d38fb88d6d36daed101587854fd68331af91 [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"
terelius429c3452016-01-21 05:42:04 -080021#include "webrtc/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,
131 bool repeat,
132 uint64_t picture_id,
Erik Språngf7c57762015-12-04 10:40:35 +0100133 uint32_t ntp_sec,
danilchap56036ff2016-03-22 11:14:09 -0700134 uint32_t ntp_frac)
Erik Språngf7c57762015-12-04 10:40:35 +0100135 : feedback_state_(feedback_state),
136 nack_size_(nack_size),
137 nack_list_(nack_list),
138 repeat_(repeat),
139 picture_id_(picture_id),
140 ntp_sec_(ntp_sec),
danilchap56036ff2016-03-22 11:14:09 -0700141 ntp_frac_(ntp_frac) {}
Erik Språng242e22b2015-05-11 10:17:43 +0200142
Erik Språngf7c57762015-12-04 10:40:35 +0100143 const FeedbackState& feedback_state_;
144 const int32_t nack_size_;
145 const uint16_t* nack_list_;
146 const bool repeat_;
147 const uint64_t picture_id_;
148 const uint32_t ntp_sec_;
149 const uint32_t ntp_frac_;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200150};
151
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000152RTCPSender::RTCPSender(
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000153 bool audio,
154 Clock* clock,
155 ReceiveStatistics* receive_statistics,
sprang86fd9ed2015-09-29 04:45:43 -0700156 RtcpPacketTypeCounterObserver* packet_type_counter_observer,
terelius429c3452016-01-21 05:42:04 -0800157 RtcEventLog* event_log,
sprang86fd9ed2015-09-29 04:45:43 -0700158 Transport* outgoing_transport)
Peter Boströmac547a62015-09-17 23:03:57 +0200159 : audio_(audio),
Erik Språng242e22b2015-05-11 10:17:43 +0200160 clock_(clock),
danilchap47a740b2015-12-15 00:30:07 -0800161 random_(clock_->TimeInMicroseconds()),
pbosda903ea2015-10-02 02:36:56 -0700162 method_(RtcpMode::kOff),
terelius429c3452016-01-21 05:42:04 -0800163 event_log_(event_log),
sprang86fd9ed2015-09-29 04:45:43 -0700164 transport_(outgoing_transport),
Erik Språng242e22b2015-05-11 10:17:43 +0200165 using_nack_(false),
166 sending_(false),
167 remb_enabled_(false),
Erik Språng242e22b2015-05-11 10:17:43 +0200168 next_time_to_send_rtcp_(0),
danilchap71fead22016-08-18 02:01:49 -0700169 timestamp_offset_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000170 last_rtp_timestamp_(0),
171 last_frame_capture_time_ms_(-1),
Erik Språng242e22b2015-05-11 10:17:43 +0200172 ssrc_(0),
173 remote_ssrc_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000174 receive_statistics_(receive_statistics),
niklase@google.com470e71d2011-07-07 08:21:25 +0000175
Erik Språng242e22b2015-05-11 10:17:43 +0200176 sequence_number_fir_(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000177
Erik Språng242e22b2015-05-11 10:17:43 +0200178 remb_bitrate_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000179
danilchap2b616392016-08-18 06:17:42 -0700180 tmmbr_send_bps_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200181 packet_oh_send_(0),
danilchap41befce2016-03-30 11:11:51 -0700182 max_payload_length_(IP_PACKET_SIZE - 28), // IPv4 + UDP by default.
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000183
Erik Språng242e22b2015-05-11 10:17:43 +0200184 app_sub_type_(0),
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200185 app_name_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200186 app_data_(nullptr),
187 app_length_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000188
Erik Språng242e22b2015-05-11 10:17:43 +0200189 xr_send_receiver_reference_time_enabled_(false),
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000190 packet_type_counter_observer_(packet_type_counter_observer) {
sprang86fd9ed2015-09-29 04:45:43 -0700191 RTC_DCHECK(transport_ != nullptr);
Erik Språng242e22b2015-05-11 10:17:43 +0200192
193 builders_[kRtcpSr] = &RTCPSender::BuildSR;
194 builders_[kRtcpRr] = &RTCPSender::BuildRR;
Erik Språng0ea42d32015-06-25 14:46:16 +0200195 builders_[kRtcpSdes] = &RTCPSender::BuildSDES;
Erik Språng242e22b2015-05-11 10:17:43 +0200196 builders_[kRtcpPli] = &RTCPSender::BuildPLI;
197 builders_[kRtcpFir] = &RTCPSender::BuildFIR;
198 builders_[kRtcpSli] = &RTCPSender::BuildSLI;
199 builders_[kRtcpRpsi] = &RTCPSender::BuildRPSI;
200 builders_[kRtcpRemb] = &RTCPSender::BuildREMB;
201 builders_[kRtcpBye] = &RTCPSender::BuildBYE;
202 builders_[kRtcpApp] = &RTCPSender::BuildAPP;
203 builders_[kRtcpTmmbr] = &RTCPSender::BuildTMMBR;
204 builders_[kRtcpTmmbn] = &RTCPSender::BuildTMMBN;
205 builders_[kRtcpNack] = &RTCPSender::BuildNACK;
sprang5e38c962016-12-01 05:18:09 -0800206 builders_[kRtcpAnyExtendedReports] = &RTCPSender::BuildExtendedReports;
niklase@google.com470e71d2011-07-07 08:21:25 +0000207}
208
danilchap162abd32015-12-10 02:39:40 -0800209RTCPSender::~RTCPSender() {}
niklase@google.com470e71d2011-07-07 08:21:25 +0000210
pbosda903ea2015-10-02 02:36:56 -0700211RtcpMode RTCPSender::Status() const {
danilchap56036ff2016-03-22 11:14:09 -0700212 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200213 return method_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000214}
215
skvlad1c392cc2016-04-01 14:46:44 -0700216void RTCPSender::SetRTCPStatus(RtcpMode new_method) {
danilchap56036ff2016-03-22 11:14:09 -0700217 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000218
skvlad1c392cc2016-04-01 14:46:44 -0700219 if (method_ == RtcpMode::kOff && new_method != RtcpMode::kOff) {
220 // When switching on, reschedule the next packet
221 next_time_to_send_rtcp_ =
Erik Språng242e22b2015-05-11 10:17:43 +0200222 clock_->TimeInMilliseconds() +
223 (audio_ ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
skvlad1c392cc2016-04-01 14:46:44 -0700224 }
225 method_ = new_method;
niklase@google.com470e71d2011-07-07 08:21:25 +0000226}
227
Erik Språng61be2a42015-04-27 13:32:52 +0200228bool RTCPSender::Sending() const {
danilchap56036ff2016-03-22 11:14:09 -0700229 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200230 return sending_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000231}
232
Erik Språng61be2a42015-04-27 13:32:52 +0200233int32_t RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
234 bool sending) {
235 bool sendRTCPBye = false;
236 {
danilchap56036ff2016-03-22 11:14:09 -0700237 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000238
pbosda903ea2015-10-02 02:36:56 -0700239 if (method_ != RtcpMode::kOff) {
Erik Språng242e22b2015-05-11 10:17:43 +0200240 if (sending == false && sending_ == true) {
Erik Språng61be2a42015-04-27 13:32:52 +0200241 // Trigger RTCP bye
242 sendRTCPBye = true;
243 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000244 }
Erik Språng242e22b2015-05-11 10:17:43 +0200245 sending_ = sending;
Erik Språng61be2a42015-04-27 13:32:52 +0200246 }
247 if (sendRTCPBye)
248 return SendRTCP(feedback_state, kRtcpBye);
249 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000250}
251
Erik Språng61be2a42015-04-27 13:32:52 +0200252bool RTCPSender::REMB() const {
danilchap56036ff2016-03-22 11:14:09 -0700253 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200254 return remb_enabled_;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000255}
256
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000257void RTCPSender::SetREMBStatus(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700258 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200259 remb_enabled_ = enable;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000260}
261
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000262void RTCPSender::SetREMBData(uint32_t bitrate,
263 const std::vector<uint32_t>& ssrcs) {
danilchap56036ff2016-03-22 11:14:09 -0700264 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200265 remb_bitrate_ = bitrate;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000266 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000267
Erik Språng242e22b2015-05-11 10:17:43 +0200268 if (remb_enabled_)
269 SetFlag(kRtcpRemb, false);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000270 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
271 // throttled by the caller.
Erik Språng242e22b2015-05-11 10:17:43 +0200272 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000273}
274
Erik Språng61be2a42015-04-27 13:32:52 +0200275bool RTCPSender::TMMBR() const {
danilchap56036ff2016-03-22 11:14:09 -0700276 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200277 return IsFlagPresent(RTCPPacketType::kRtcpTmmbr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000278}
279
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000280void RTCPSender::SetTMMBRStatus(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700281 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200282 if (enable) {
283 SetFlag(RTCPPacketType::kRtcpTmmbr, false);
284 } else {
285 ConsumeFlag(RTCPPacketType::kRtcpTmmbr, true);
286 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000287}
288
danilchap41befce2016-03-30 11:11:51 -0700289void RTCPSender::SetMaxPayloadLength(size_t max_payload_length) {
290 max_payload_length_ = max_payload_length;
291}
292
danilchap71fead22016-08-18 02:01:49 -0700293void RTCPSender::SetTimestampOffset(uint32_t timestamp_offset) {
danilchap56036ff2016-03-22 11:14:09 -0700294 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap71fead22016-08-18 02:01:49 -0700295 timestamp_offset_ = timestamp_offset;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000296}
297
298void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
299 int64_t capture_time_ms) {
danilchap56036ff2016-03-22 11:14:09 -0700300 rtc::CritScope lock(&critical_section_rtcp_sender_);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000301 last_rtp_timestamp_ = rtp_timestamp;
302 if (capture_time_ms < 0) {
303 // We don't currently get a capture time from VoiceEngine.
Erik Språng242e22b2015-05-11 10:17:43 +0200304 last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000305 } else {
306 last_frame_capture_time_ms_ = capture_time_ms;
307 }
308}
309
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000310void RTCPSender::SetSSRC(uint32_t ssrc) {
danilchap56036ff2016-03-22 11:14:09 -0700311 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000312
Erik Språng242e22b2015-05-11 10:17:43 +0200313 if (ssrc_ != 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200314 // not first SetSSRC, probably due to a collision
315 // schedule a new RTCP report
316 // make sure that we send a RTP packet
Erik Språng242e22b2015-05-11 10:17:43 +0200317 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
Erik Språng61be2a42015-04-27 13:32:52 +0200318 }
Erik Språng242e22b2015-05-11 10:17:43 +0200319 ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000320}
321
Erik Språng61be2a42015-04-27 13:32:52 +0200322void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
danilchap56036ff2016-03-22 11:14:09 -0700323 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200324 remote_ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000325}
326
Peter Boström9ba52f82015-06-01 14:12:28 +0200327int32_t RTCPSender::SetCNAME(const char* c_name) {
328 if (!c_name)
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000329 return -1;
330
kwiberg352444f2016-11-28 15:58:53 -0800331 RTC_DCHECK_LT(strlen(c_name), RTCP_CNAME_SIZE);
danilchap56036ff2016-03-22 11:14:09 -0700332 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200333 cname_ = c_name;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000334 return 0;
335}
336
Erik Språng0ea42d32015-06-25 14:46:16 +0200337int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC, const char* c_name) {
danilchap56036ff2016-03-22 11:14:09 -0700338 RTC_DCHECK(c_name);
kwiberg352444f2016-11-28 15:58:53 -0800339 RTC_DCHECK_LT(strlen(c_name), RTCP_CNAME_SIZE);
danilchap56036ff2016-03-22 11:14:09 -0700340 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200341 if (csrc_cnames_.size() >= kRtpCsrcSize)
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000342 return -1;
Erik Språng0ea42d32015-06-25 14:46:16 +0200343
344 csrc_cnames_[SSRC] = c_name;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000345 return 0;
346}
347
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000348int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
danilchap56036ff2016-03-22 11:14:09 -0700349 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200350 auto it = csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000351
Erik Språng242e22b2015-05-11 10:17:43 +0200352 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000353 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200354
Erik Språng242e22b2015-05-11 10:17:43 +0200355 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000356 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000357}
358
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000359bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
danilchap162abd32015-12-10 02:39:40 -0800360 /*
361 For audio we use a fix 5 sec interval
niklase@google.com470e71d2011-07-07 08:21:25 +0000362
danilchap162abd32015-12-10 02:39:40 -0800363 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
364 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
365 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000366
367
danilchap162abd32015-12-10 02:39:40 -0800368 From RFC 3550
niklase@google.com470e71d2011-07-07 08:21:25 +0000369
danilchap162abd32015-12-10 02:39:40 -0800370 MAX RTCP BW is 5% if the session BW
371 A send report is approximately 65 bytes inc CNAME
372 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000373
danilchap162abd32015-12-10 02:39:40 -0800374 The RECOMMENDED value for the reduced minimum in seconds is 360
375 divided by the session bandwidth in kilobits/second. This minimum
376 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
niklase@google.com470e71d2011-07-07 08:21:25 +0000377
danilchap162abd32015-12-10 02:39:40 -0800378 If the participant has not yet sent an RTCP packet (the variable
379 initial is true), the constant Tmin is set to 2.5 seconds, else it
380 is set to 5 seconds.
niklase@google.com470e71d2011-07-07 08:21:25 +0000381
danilchap162abd32015-12-10 02:39:40 -0800382 The interval between RTCP packets is varied randomly over the
383 range [0.5,1.5] times the calculated interval to avoid unintended
384 synchronization of all participants
niklase@google.com470e71d2011-07-07 08:21:25 +0000385
danilchap162abd32015-12-10 02:39:40 -0800386 if we send
387 If the participant is a sender (we_sent true), the constant C is
388 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
389 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
390 number of senders.
niklase@google.com470e71d2011-07-07 08:21:25 +0000391
danilchap162abd32015-12-10 02:39:40 -0800392 if we receive only
393 If we_sent is not true, the constant C is set
394 to the average RTCP packet size divided by 75% of the RTCP
395 bandwidth. The constant n is set to the number of receivers
396 (members - senders). If the number of senders is greater than
397 25%, senders and receivers are treated together.
niklase@google.com470e71d2011-07-07 08:21:25 +0000398
danilchap162abd32015-12-10 02:39:40 -0800399 reconsideration NOT required for peer-to-peer
400 "timer reconsideration" is
401 employed. This algorithm implements a simple back-off mechanism
402 which causes users to hold back RTCP packet transmission if the
403 group sizes are increasing.
niklase@google.com470e71d2011-07-07 08:21:25 +0000404
danilchap162abd32015-12-10 02:39:40 -0800405 n = number of members
406 C = avg_size/(rtcpBW/4)
niklase@google.com470e71d2011-07-07 08:21:25 +0000407
danilchap162abd32015-12-10 02:39:40 -0800408 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
niklase@google.com470e71d2011-07-07 08:21:25 +0000409
danilchap162abd32015-12-10 02:39:40 -0800410 4. The calculated interval T is set to a number uniformly distributed
411 between 0.5 and 1.5 times the deterministic calculated interval.
niklase@google.com470e71d2011-07-07 08:21:25 +0000412
danilchap162abd32015-12-10 02:39:40 -0800413 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
414 for the fact that the timer reconsideration algorithm converges to
415 a value of the RTCP bandwidth below the intended average
416 */
niklase@google.com470e71d2011-07-07 08:21:25 +0000417
Erik Språng242e22b2015-05-11 10:17:43 +0200418 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000419
danilchap56036ff2016-03-22 11:14:09 -0700420 rtc::CritScope lock(&critical_section_rtcp_sender_);
xians@webrtc.org8738d272011-11-25 13:43:53 +0000421
pbosda903ea2015-10-02 02:36:56 -0700422 if (method_ == RtcpMode::kOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000423 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000424
Erik Språng242e22b2015-05-11 10:17:43 +0200425 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200426 // for video key-frames we want to send the RTCP before the large key-frame
427 // if we have a 100 ms margin
428 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
429 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000430
Erik Språng242e22b2015-05-11 10:17:43 +0200431 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200432 return true;
433 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200434 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200435 // wrap
436 return true;
437 }
438 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000439}
440
danilchap56036ff2016-03-22 11:14:09 -0700441std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSR(const RtcpContext& ctx) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200442 // Timestamp shouldn't be estimated before first media frame.
443 RTC_DCHECK_GE(last_frame_capture_time_ms_, 0);
Erik Språng61be2a42015-04-27 13:32:52 +0200444 // The timestamp of this RTCP packet should be estimated as the timestamp of
445 // the frame being captured at this moment. We are calculating that
446 // timestamp as the last frame's timestamp + the time since the last frame
447 // was captured.
solenbergb19d2882016-10-03 06:22:25 -0700448 uint32_t rtp_rate =
449 (audio_ ? kBogusRtpRateForAudioRtcp : kVideoPayloadTypeFrequency) / 1000;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200450 uint32_t rtp_timestamp =
danilchap71fead22016-08-18 02:01:49 -0700451 timestamp_offset_ + last_rtp_timestamp_ +
solenbergb19d2882016-10-03 06:22:25 -0700452 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) * rtp_rate;
niklase@google.com470e71d2011-07-07 08:21:25 +0000453
Erik Språngf7c57762015-12-04 10:40:35 +0100454 rtcp::SenderReport* report = new rtcp::SenderReport();
danilchap822a16f2016-09-27 09:27:47 -0700455 report->SetSenderSsrc(ssrc_);
456 report->SetNtp(NtpTime(ctx.ntp_sec_, ctx.ntp_frac_));
457 report->SetRtpTimestamp(rtp_timestamp);
458 report->SetPacketCount(ctx.feedback_state_.packets_sent);
459 report->SetOctetCount(ctx.feedback_state_.media_bytes_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000460
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200461 for (auto it : report_blocks_)
danilchap822a16f2016-09-27 09:27:47 -0700462 report->AddReportBlock(it.second);
niklase@google.com470e71d2011-07-07 08:21:25 +0000463
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200464 report_blocks_.clear();
Erik Språngf7c57762015-12-04 10:40:35 +0100465
danilchap56036ff2016-03-22 11:14:09 -0700466 return std::unique_ptr<rtcp::RtcpPacket>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000467}
468
danilchap56036ff2016-03-22 11:14:09 -0700469std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSDES(
Erik Språngf7c57762015-12-04 10:40:35 +0100470 const RtcpContext& ctx) {
Erik Språng0ea42d32015-06-25 14:46:16 +0200471 size_t length_cname = cname_.length();
kwiberg352444f2016-11-28 15:58:53 -0800472 RTC_CHECK_LT(length_cname, RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000473
Erik Språngf7c57762015-12-04 10:40:35 +0100474 rtcp::Sdes* sdes = new rtcp::Sdes();
danilchap822a16f2016-09-27 09:27:47 -0700475 sdes->AddCName(ssrc_, cname_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200476
477 for (const auto it : csrc_cnames_)
danilchap822a16f2016-09-27 09:27:47 -0700478 sdes->AddCName(it.first, it.second);
Erik Språng0ea42d32015-06-25 14:46:16 +0200479
danilchap56036ff2016-03-22 11:14:09 -0700480 return std::unique_ptr<rtcp::RtcpPacket>(sdes);
niklase@google.com470e71d2011-07-07 08:21:25 +0000481}
482
danilchap56036ff2016-03-22 11:14:09 -0700483std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildRR(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100484 rtcp::ReceiverReport* report = new rtcp::ReceiverReport();
danilchap822a16f2016-09-27 09:27:47 -0700485 report->SetSenderSsrc(ssrc_);
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200486 for (auto it : report_blocks_)
danilchap822a16f2016-09-27 09:27:47 -0700487 report->AddReportBlock(it.second);
Erik Språng61be2a42015-04-27 13:32:52 +0200488
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200489 report_blocks_.clear();
danilchap56036ff2016-03-22 11:14:09 -0700490 return std::unique_ptr<rtcp::RtcpPacket>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000491}
492
danilchap56036ff2016-03-22 11:14:09 -0700493std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildPLI(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100494 rtcp::Pli* pli = new rtcp::Pli();
danilchap822a16f2016-09-27 09:27:47 -0700495 pli->SetSenderSsrc(ssrc_);
496 pli->SetMediaSsrc(remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200497
Erik Språng242e22b2015-05-11 10:17:43 +0200498 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
499 "RTCPSender::PLI");
500 ++packet_type_counter_.pli_packets;
501 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
502 ssrc_, packet_type_counter_.pli_packets);
503
danilchap56036ff2016-03-22 11:14:09 -0700504 return std::unique_ptr<rtcp::RtcpPacket>(pli);
Erik Språng61be2a42015-04-27 13:32:52 +0200505}
506
danilchap56036ff2016-03-22 11:14:09 -0700507std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildFIR(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100508 if (!ctx.repeat_)
sprang62dae192015-08-05 02:35:35 -0700509 ++sequence_number_fir_; // Do not increase if repetition.
niklase@google.com470e71d2011-07-07 08:21:25 +0000510
Erik Språngf7c57762015-12-04 10:40:35 +0100511 rtcp::Fir* fir = new rtcp::Fir();
danilchap822a16f2016-09-27 09:27:47 -0700512 fir->SetSenderSsrc(ssrc_);
513 fir->AddRequestTo(remote_ssrc_, sequence_number_fir_);
Erik Språng242e22b2015-05-11 10:17:43 +0200514
515 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
516 "RTCPSender::FIR");
517 ++packet_type_counter_.fir_packets;
518 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
519 ssrc_, packet_type_counter_.fir_packets);
520
danilchap56036ff2016-03-22 11:14:09 -0700521 return std::unique_ptr<rtcp::RtcpPacket>(fir);
niklase@google.com470e71d2011-07-07 08:21:25 +0000522}
523
524/*
525 0 1 2 3
526 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
527 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
528 | First | Number | PictureID |
529 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
530*/
danilchap56036ff2016-03-22 11:14:09 -0700531std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSLI(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100532 rtcp::Sli* sli = new rtcp::Sli();
danilchap822a16f2016-09-27 09:27:47 -0700533 sli->SetSenderSsrc(ssrc_);
534 sli->SetMediaSsrc(remote_ssrc_);
sprang0365a272015-08-11 01:02:37 -0700535 // Crop picture id to 6 least significant bits.
danilchap822a16f2016-09-27 09:27:47 -0700536 sli->AddPictureId(ctx.picture_id_ & 0x3F);
sprang0365a272015-08-11 01:02:37 -0700537
danilchap56036ff2016-03-22 11:14:09 -0700538 return std::unique_ptr<rtcp::RtcpPacket>(sli);
niklase@google.com470e71d2011-07-07 08:21:25 +0000539}
540
541/*
542 0 1 2 3
543 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
544 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
545 | PB |0| Payload Type| Native RPSI bit string |
546 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
547 | defined per codec ... | Padding (0) |
548 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
549*/
550/*
551* Note: not generic made for VP8
552*/
danilchap56036ff2016-03-22 11:14:09 -0700553std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildRPSI(
Erik Språngf7c57762015-12-04 10:40:35 +0100554 const RtcpContext& ctx) {
555 if (ctx.feedback_state_.send_payload_type == 0xFF)
556 return nullptr;
Erik Språng242e22b2015-05-11 10:17:43 +0200557
Erik Språngf7c57762015-12-04 10:40:35 +0100558 rtcp::Rpsi* rpsi = new rtcp::Rpsi();
danilchap822a16f2016-09-27 09:27:47 -0700559 rpsi->SetSenderSsrc(ssrc_);
560 rpsi->SetMediaSsrc(remote_ssrc_);
561 rpsi->SetPayloadType(ctx.feedback_state_.send_payload_type);
562 rpsi->SetPictureId(ctx.picture_id_);
sprangcf7f54d2015-08-13 04:37:42 -0700563
danilchap56036ff2016-03-22 11:14:09 -0700564 return std::unique_ptr<rtcp::RtcpPacket>(rpsi);
niklase@google.com470e71d2011-07-07 08:21:25 +0000565}
566
danilchap56036ff2016-03-22 11:14:09 -0700567std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildREMB(
Erik Språngf7c57762015-12-04 10:40:35 +0100568 const RtcpContext& ctx) {
569 rtcp::Remb* remb = new rtcp::Remb();
danilchap822a16f2016-09-27 09:27:47 -0700570 remb->SetSenderSsrc(ssrc_);
571 remb->SetBitrateBps(remb_bitrate_);
572 remb->SetSsrcs(remb_ssrcs_);
Erik Språng61be2a42015-04-27 13:32:52 +0200573
Erik Språng242e22b2015-05-11 10:17:43 +0200574 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
575 "RTCPSender::REMB");
576
danilchap56036ff2016-03-22 11:14:09 -0700577 return std::unique_ptr<rtcp::RtcpPacket>(remb);
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000578}
579
Erik Språng61be2a42015-04-27 13:32:52 +0200580void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
danilchap56036ff2016-03-22 11:14:09 -0700581 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap2b616392016-08-18 06:17:42 -0700582 tmmbr_send_bps_ = target_bitrate;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000583}
584
danilchap56036ff2016-03-22 11:14:09 -0700585std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBR(
Erik Språngf7c57762015-12-04 10:40:35 +0100586 const RtcpContext& ctx) {
587 if (ctx.feedback_state_.module == nullptr)
588 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200589 // Before sending the TMMBR check the received TMMBN, only an owner is
590 // allowed to raise the bitrate:
591 // * If the sender is an owner of the TMMBN -> send TMMBR
592 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000593
Erik Språng61be2a42015-04-27 13:32:52 +0200594 // get current bounding set from RTCP receiver
danilchap2b616392016-08-18 06:17:42 -0700595 bool tmmbr_owner = false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000596
Erik Språng242e22b2015-05-11 10:17:43 +0200597 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
598 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
Erik Språng61be2a42015-04-27 13:32:52 +0200599 // since RTCPreceiver is not doing the reverse we should be fine
danilchap2b616392016-08-18 06:17:42 -0700600 std::vector<rtcp::TmmbItem> candidates =
601 ctx.feedback_state_.module->BoundingSet(&tmmbr_owner);
niklase@google.com470e71d2011-07-07 08:21:25 +0000602
danilchap2b616392016-08-18 06:17:42 -0700603 if (!candidates.empty()) {
604 for (const auto& candidate : candidates) {
605 if (candidate.bitrate_bps() == tmmbr_send_bps_ &&
606 candidate.packet_overhead() == packet_oh_send_) {
Erik Språngf7c57762015-12-04 10:40:35 +0100607 // Do not send the same tuple.
608 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200609 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000610 }
danilchap2b616392016-08-18 06:17:42 -0700611 if (!tmmbr_owner) {
612 // Use received bounding set as candidate set.
613 // Add current tuple.
614 candidates.emplace_back(ssrc_, tmmbr_send_bps_, packet_oh_send_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000615
danilchap2b616392016-08-18 06:17:42 -0700616 // Find bounding set.
danilchap2f69ce92016-08-16 03:21:38 -0700617 std::vector<rtcp::TmmbItem> bounding =
618 TMMBRHelp::FindBoundingSet(std::move(candidates));
danilchap2b616392016-08-18 06:17:42 -0700619 tmmbr_owner = TMMBRHelp::IsOwner(bounding, ssrc_);
620 if (!tmmbr_owner) {
Erik Språngf7c57762015-12-04 10:40:35 +0100621 // Did not enter bounding set, no meaning to send this request.
622 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200623 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000624 }
Erik Språng61be2a42015-04-27 13:32:52 +0200625 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000626
danilchap2b616392016-08-18 06:17:42 -0700627 if (!tmmbr_send_bps_)
Erik Språngf7c57762015-12-04 10:40:35 +0100628 return nullptr;
sprang81a3e602015-08-21 05:30:11 -0700629
Erik Språngf7c57762015-12-04 10:40:35 +0100630 rtcp::Tmmbr* tmmbr = new rtcp::Tmmbr();
danilchap822a16f2016-09-27 09:27:47 -0700631 tmmbr->SetSenderSsrc(ssrc_);
danilchapf174e3a2016-02-05 04:56:36 -0800632 rtcp::TmmbItem request;
633 request.set_ssrc(remote_ssrc_);
danilchap2b616392016-08-18 06:17:42 -0700634 request.set_bitrate_bps(tmmbr_send_bps_);
danilchapf174e3a2016-02-05 04:56:36 -0800635 request.set_packet_overhead(packet_oh_send_);
danilchap822a16f2016-09-27 09:27:47 -0700636 tmmbr->AddTmmbr(request);
Erik Språngf7c57762015-12-04 10:40:35 +0100637
danilchap56036ff2016-03-22 11:14:09 -0700638 return std::unique_ptr<rtcp::RtcpPacket>(tmmbr);
Erik Språng61be2a42015-04-27 13:32:52 +0200639}
640
danilchap56036ff2016-03-22 11:14:09 -0700641std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBN(
Erik Språngf7c57762015-12-04 10:40:35 +0100642 const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100643 rtcp::Tmmbn* tmmbn = new rtcp::Tmmbn();
danilchap822a16f2016-09-27 09:27:47 -0700644 tmmbn->SetSenderSsrc(ssrc_);
danilchap6eaa3a42016-05-09 10:59:50 -0700645 for (const rtcp::TmmbItem& tmmbr : tmmbn_to_send_) {
646 if (tmmbr.bitrate_bps() > 0) {
danilchap822a16f2016-09-27 09:27:47 -0700647 tmmbn->AddTmmbr(tmmbr);
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000648 }
Erik Språng61be2a42015-04-27 13:32:52 +0200649 }
sprangd83df502015-08-27 01:05:08 -0700650
danilchap56036ff2016-03-22 11:14:09 -0700651 return std::unique_ptr<rtcp::RtcpPacket>(tmmbn);
niklase@google.com470e71d2011-07-07 08:21:25 +0000652}
653
danilchap56036ff2016-03-22 11:14:09 -0700654std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildAPP(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100655 rtcp::App* app = new rtcp::App();
danilchap822a16f2016-09-27 09:27:47 -0700656 app->SetSsrc(ssrc_);
657 app->SetSubType(app_sub_type_);
658 app->SetName(app_name_);
659 app->SetData(app_data_.get(), app_length_);
Erik Språng521875a2015-09-01 10:11:16 +0200660
danilchap56036ff2016-03-22 11:14:09 -0700661 return std::unique_ptr<rtcp::RtcpPacket>(app);
Erik Språng61be2a42015-04-27 13:32:52 +0200662}
663
danilchap56036ff2016-03-22 11:14:09 -0700664std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildNACK(
Erik Språngf7c57762015-12-04 10:40:35 +0100665 const RtcpContext& ctx) {
666 rtcp::Nack* nack = new rtcp::Nack();
danilchap822a16f2016-09-27 09:27:47 -0700667 nack->SetSenderSsrc(ssrc_);
668 nack->SetMediaSsrc(remote_ssrc_);
669 nack->SetPacketIds(ctx.nack_list_, ctx.nack_size_);
Erik Språng61be2a42015-04-27 13:32:52 +0200670
671 // Report stats.
672 NACKStringBuilder stringBuilder;
Erik Språngf7c57762015-12-04 10:40:35 +0100673 for (int idx = 0; idx < ctx.nack_size_; ++idx) {
674 stringBuilder.PushNACK(ctx.nack_list_[idx]);
675 nack_stats_.ReportRequest(ctx.nack_list_[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +0200676 }
Erik Språng61be2a42015-04-27 13:32:52 +0200677 packet_type_counter_.nack_requests = nack_stats_.requests();
678 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +0200679
680 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
681 "RTCPSender::NACK", "nacks",
682 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
683 ++packet_type_counter_.nack_packets;
684 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
685 ssrc_, packet_type_counter_.nack_packets);
686
danilchap56036ff2016-03-22 11:14:09 -0700687 return std::unique_ptr<rtcp::RtcpPacket>(nack);
Erik Språng61be2a42015-04-27 13:32:52 +0200688}
689
danilchap56036ff2016-03-22 11:14:09 -0700690std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildBYE(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100691 rtcp::Bye* bye = new rtcp::Bye();
danilchap822a16f2016-09-27 09:27:47 -0700692 bye->SetSenderSsrc(ssrc_);
693 bye->SetCsrcs(csrcs_);
sprangd8ee4f92015-08-24 03:25:19 -0700694
danilchap56036ff2016-03-22 11:14:09 -0700695 return std::unique_ptr<rtcp::RtcpPacket>(bye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000696}
697
sprang5e38c962016-12-01 05:18:09 -0800698std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildExtendedReports(
Erik Språngf7c57762015-12-04 10:40:35 +0100699 const RtcpContext& ctx) {
sprang5e38c962016-12-01 05:18:09 -0800700 std::unique_ptr<rtcp::ExtendedReports> xr(new rtcp::ExtendedReports());
danilchap822a16f2016-09-27 09:27:47 -0700701 xr->SetSenderSsrc(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000702
sprang5e38c962016-12-01 05:18:09 -0800703 if (!sending_ && xr_send_receiver_reference_time_enabled_) {
704 rtcp::Rrtr rrtr;
705 rrtr.SetNtp(NtpTime(ctx.ntp_sec_, ctx.ntp_frac_));
706 xr->SetRrtr(rrtr);
707 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000708
sprang5e38c962016-12-01 05:18:09 -0800709 if (ctx.feedback_state_.has_last_xr_rr) {
710 xr->AddDlrrItem(ctx.feedback_state_.last_xr_rr);
711 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000712
sprang5e38c962016-12-01 05:18:09 -0800713 if (video_bitrate_allocation_) {
714 rtcp::TargetBitrate target_bitrate;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000715
sprang5e38c962016-12-01 05:18:09 -0800716 for (int sl = 0; sl < kMaxSpatialLayers; ++sl) {
717 for (int tl = 0; tl < kMaxTemporalStreams; ++tl) {
718 uint32_t layer_bitrate_bps =
719 video_bitrate_allocation_->GetBitrate(sl, tl);
720 if (layer_bitrate_bps > 0)
721 target_bitrate.AddTargetBitrate(sl, tl, layer_bitrate_bps / 1000);
722 }
723 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000724
sprang5e38c962016-12-01 05:18:09 -0800725 xr->SetTargetBitrate(target_bitrate);
726 video_bitrate_allocation_.reset();
727 }
Erik Språngca28fdc2015-08-31 14:00:50 +0200728
sprang5e38c962016-12-01 05:18:09 -0800729 if (xr_voip_metric_) {
730 rtcp::VoipMetric voip;
731 voip.SetMediaSsrc(remote_ssrc_);
732 voip.SetVoipMetric(*xr_voip_metric_);
733 xr_voip_metric_.reset();
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000734
sprang5e38c962016-12-01 05:18:09 -0800735 xr->SetVoipMetric(voip);
736 }
Erik Språngca28fdc2015-08-31 14:00:50 +0200737
sprang5e38c962016-12-01 05:18:09 -0800738 return std::move(xr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000739}
740
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000741int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200742 RTCPPacketType packetType,
743 int32_t nack_size,
744 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000745 bool repeat,
746 uint64_t pictureID) {
Erik Språng242e22b2015-05-11 10:17:43 +0200747 return SendCompoundRTCP(
748 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
749 nack_size, nack_list, repeat, pictureID);
750}
751
752int32_t RTCPSender::SendCompoundRTCP(
753 const FeedbackState& feedback_state,
Erik Språngf7c57762015-12-04 10:40:35 +0100754 const std::set<RTCPPacketType>& packet_types,
Erik Språng242e22b2015-05-11 10:17:43 +0200755 int32_t nack_size,
756 const uint16_t* nack_list,
757 bool repeat,
758 uint64_t pictureID) {
terelius429c3452016-01-21 05:42:04 -0800759 PacketContainer container(transport_, event_log_);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000760 {
danilchap56036ff2016-03-22 11:14:09 -0700761 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbosda903ea2015-10-02 02:36:56 -0700762 if (method_ == RtcpMode::kOff) {
Erik Språng61be2a42015-04-27 13:32:52 +0200763 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
764 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +0000765 }
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200766 // Add all flags as volatile. Non volatile entries will not be overwritten.
767 // All new volatile flags added will be consumed by the end of this call.
768 SetFlags(packet_types, true);
769
770 // Prevent sending streams to send SR before any media has been sent.
771 const bool can_calculate_rtp_timestamp = (last_frame_capture_time_ms_ >= 0);
772 if (!can_calculate_rtp_timestamp) {
773 bool consumed_sr_flag = ConsumeFlag(kRtcpSr);
774 bool consumed_report_flag = sending_ && ConsumeFlag(kRtcpReport);
775 bool sender_report = consumed_report_flag || consumed_sr_flag;
776 if (sender_report && AllVolatileFlagsConsumed()) {
777 // This call was for Sender Report and nothing else.
778 return 0;
779 }
780 if (sending_ && method_ == RtcpMode::kCompound) {
781 // Not allowed to send any RTCP packet without sender report.
782 return -1;
783 }
784 }
785
786 if (packet_type_counter_.first_packet_time_ms == -1)
787 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språngf7c57762015-12-04 10:40:35 +0100788
789 // We need to send our NTP even if we haven't received any reports.
790 uint32_t ntp_sec;
791 uint32_t ntp_frac;
792 clock_->CurrentNtp(ntp_sec, ntp_frac);
793 RtcpContext context(feedback_state, nack_size, nack_list, repeat, pictureID,
danilchap56036ff2016-03-22 11:14:09 -0700794 ntp_sec, ntp_frac);
Erik Språngf7c57762015-12-04 10:40:35 +0100795
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200796 PrepareReport(feedback_state);
Erik Språngf7c57762015-12-04 10:40:35 +0100797
danilchap56036ff2016-03-22 11:14:09 -0700798 std::unique_ptr<rtcp::RtcpPacket> packet_bye;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800799
Erik Språngf7c57762015-12-04 10:40:35 +0100800 auto it = report_flags_.begin();
801 while (it != report_flags_.end()) {
802 auto builder_it = builders_.find(it->type);
sprang5e38c962016-12-01 05:18:09 -0800803 RTC_DCHECK(builder_it != builders_.end())
804 << "Could not find builder for packet type " << it->type;
Erik Språngf7c57762015-12-04 10:40:35 +0100805 if (it->is_volatile) {
806 report_flags_.erase(it++);
807 } else {
808 ++it;
809 }
810
811 BuilderFunc func = builder_it->second;
danilchap56036ff2016-03-22 11:14:09 -0700812 std::unique_ptr<rtcp::RtcpPacket> packet = (this->*func)(context);
Erik Språngf7c57762015-12-04 10:40:35 +0100813 if (packet.get() == nullptr)
814 return -1;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800815 // If there is a BYE, don't append now - save it and append it
816 // at the end later.
817 if (builder_it->first == kRtcpBye) {
818 packet_bye = std::move(packet);
819 } else {
820 container.Append(packet.release());
821 }
822 }
823
824 // Append the BYE now at the end
825 if (packet_bye) {
826 container.Append(packet_bye.release());
Erik Språngf7c57762015-12-04 10:40:35 +0100827 }
828
829 if (packet_type_counter_observer_ != nullptr) {
830 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
831 remote_ssrc_, packet_type_counter_);
832 }
833
834 RTC_DCHECK(AllVolatileFlagsConsumed());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000835 }
Erik Språng61be2a42015-04-27 13:32:52 +0200836
danilchap41befce2016-03-30 11:11:51 -0700837 size_t bytes_sent = container.SendPackets(max_payload_length_);
Erik Språngf7c57762015-12-04 10:40:35 +0100838 return bytes_sent == 0 ? -1 : 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000839}
840
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200841void RTCPSender::PrepareReport(const FeedbackState& feedback_state) {
Erik Språng242e22b2015-05-11 10:17:43 +0200842 bool generate_report;
843 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
844 // Report type already explicitly set, don't automatically populate.
845 generate_report = true;
henrikg91d6ede2015-09-17 00:24:34 -0700846 RTC_DCHECK(ConsumeFlag(kRtcpReport) == false);
Erik Språng242e22b2015-05-11 10:17:43 +0200847 } else {
848 generate_report =
pbosda903ea2015-10-02 02:36:56 -0700849 (ConsumeFlag(kRtcpReport) && method_ == RtcpMode::kReducedSize) ||
850 method_ == RtcpMode::kCompound;
Erik Språng242e22b2015-05-11 10:17:43 +0200851 if (generate_report)
852 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000853 }
854
Erik Språng0ea42d32015-06-25 14:46:16 +0200855 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
Erik Språng242e22b2015-05-11 10:17:43 +0200856 SetFlag(kRtcpSdes, true);
857
Erik Språng242e22b2015-05-11 10:17:43 +0200858 if (generate_report) {
sprang5e38c962016-12-01 05:18:09 -0800859 if ((!sending_ && xr_send_receiver_reference_time_enabled_) ||
860 feedback_state.has_last_xr_rr || video_bitrate_allocation_) {
861 SetFlag(kRtcpAnyExtendedReports, true);
862 }
Erik Språng242e22b2015-05-11 10:17:43 +0200863
864 // generate next time to send an RTCP report
danilchap47a740b2015-12-15 00:30:07 -0800865 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000866
danilchap47a740b2015-12-15 00:30:07 -0800867 if (!audio_) {
Erik Språng242e22b2015-05-11 10:17:43 +0200868 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200869 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
870 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
871 if (send_bitrate_kbit != 0)
872 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000873 }
Erik Språng61be2a42015-04-27 13:32:52 +0200874 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
875 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
Erik Språng61be2a42015-04-27 13:32:52 +0200876 }
danilchap47a740b2015-12-15 00:30:07 -0800877 // The interval between RTCP packets is varied randomly over the
878 // range [1/2,3/2] times the calculated interval.
879 uint32_t timeToNext =
880 random_.Rand(minIntervalMs * 1 / 2, minIntervalMs * 3 / 2);
Erik Språng242e22b2015-05-11 10:17:43 +0200881 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000882
Per83d09102016-04-15 14:59:13 +0200883 if (receive_statistics_) {
884 StatisticianMap statisticians =
885 receive_statistics_->GetActiveStatisticians();
886 RTC_DCHECK(report_blocks_.empty());
887 for (auto& it : statisticians) {
888 AddReportBlock(feedback_state, it.first, it.second);
889 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000890 }
891 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000892}
893
danilchapa72e7342015-12-22 08:07:45 -0800894bool RTCPSender::AddReportBlock(const FeedbackState& feedback_state,
895 uint32_t ssrc,
896 StreamStatistician* statistician) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000897 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000898 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000899 if (!statistician->GetStatistics(&stats, true))
900 return false;
danilchapa72e7342015-12-22 08:07:45 -0800901
902 if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) {
903 LOG(LS_WARNING) << "Too many report blocks.";
904 return false;
905 }
906 RTC_DCHECK(report_blocks_.find(ssrc) == report_blocks_.end());
907 rtcp::ReportBlock* block = &report_blocks_[ssrc];
danilchap822a16f2016-09-27 09:27:47 -0700908 block->SetMediaSsrc(ssrc);
909 block->SetFractionLost(stats.fraction_lost);
910 if (!block->SetCumulativeLost(stats.cumulative_lost)) {
danilchapa72e7342015-12-22 08:07:45 -0800911 report_blocks_.erase(ssrc);
912 LOG(LS_WARNING) << "Cumulative lost is oversized.";
913 return false;
914 }
danilchap822a16f2016-09-27 09:27:47 -0700915 block->SetExtHighestSeqNum(stats.extended_max_sequence_number);
916 block->SetJitter(stats.jitter);
917 block->SetLastSr(feedback_state.remote_sr);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000918
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200919 // TODO(sprang): Do we really need separate time stamps for each report?
920 // Get our NTP as late as possible to avoid a race.
921 uint32_t ntp_secs;
922 uint32_t ntp_frac;
923 clock_->CurrentNtp(ntp_secs, ntp_frac);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000924
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200925 // Delay since last received report.
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000926 if ((feedback_state.last_rr_ntp_secs != 0) ||
927 (feedback_state.last_rr_ntp_frac != 0)) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200928 // Get the 16 lowest bits of seconds and the 16 highest bits of fractions.
929 uint32_t now = ntp_secs & 0x0000FFFF;
Erik Språng61be2a42015-04-27 13:32:52 +0200930 now <<= 16;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200931 now += (ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000932
Erik Språng61be2a42015-04-27 13:32:52 +0200933 uint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
934 receiveTime <<= 16;
935 receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000936
danilchap822a16f2016-09-27 09:27:47 -0700937 block->SetDelayLastSr(now - receiveTime);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000938 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000939 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000940}
941
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000942void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
kwiberg352444f2016-11-28 15:58:53 -0800943 RTC_DCHECK_LE(csrcs.size(), kRtpCsrcSize);
danilchap56036ff2016-03-22 11:14:09 -0700944 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000945 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +0000946}
947
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000948int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
949 uint32_t name,
950 const uint8_t* data,
951 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +0200952 if (length % 4 != 0) {
953 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
954 return -1;
955 }
danilchap56036ff2016-03-22 11:14:09 -0700956 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000957
Erik Språng242e22b2015-05-11 10:17:43 +0200958 SetFlag(kRtcpApp, true);
959 app_sub_type_ = subType;
960 app_name_ = name;
961 app_data_.reset(new uint8_t[length]);
962 app_length_ = length;
963 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +0200964 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000965}
966
spranga790d832016-12-02 07:29:44 -0800967// TODO(sprang): Remove support for VoIP metrics? (Not used in receiver.)
Erik Språng61be2a42015-04-27 13:32:52 +0200968int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
danilchap56036ff2016-03-22 11:14:09 -0700969 rtc::CritScope lock(&critical_section_rtcp_sender_);
sprang5e38c962016-12-01 05:18:09 -0800970 xr_voip_metric_.emplace(*VoIPMetric);
niklase@google.com470e71d2011-07-07 08:21:25 +0000971
sprang5e38c962016-12-01 05:18:09 -0800972 SetFlag(kRtcpAnyExtendedReports, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200973 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000974}
975
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000976void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700977 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200978 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000979}
980
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000981bool RTCPSender::RtcpXrReceiverReferenceTime() const {
danilchap56036ff2016-03-22 11:14:09 -0700982 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200983 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000984}
985
danilchap853ecb22016-08-22 08:26:15 -0700986void RTCPSender::SetTmmbn(std::vector<rtcp::TmmbItem> bounding_set) {
danilchap56036ff2016-03-22 11:14:09 -0700987 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap853ecb22016-08-22 08:26:15 -0700988 tmmbn_to_send_ = std::move(bounding_set);
danilchap6eaa3a42016-05-09 10:59:50 -0700989 SetFlag(kRtcpTmmbn, true);
niklase@google.com470e71d2011-07-07 08:21:25 +0000990}
Erik Språng61be2a42015-04-27 13:32:52 +0200991
sprang5e38c962016-12-01 05:18:09 -0800992void RTCPSender::SetFlag(uint32_t type, bool is_volatile) {
993 if (type & kRtcpAnyExtendedReports) {
994 report_flags_.insert(ReportFlag(kRtcpAnyExtendedReports, is_volatile));
995 } else {
996 report_flags_.insert(ReportFlag(type, is_volatile));
997 }
Erik Språng242e22b2015-05-11 10:17:43 +0200998}
999
1000void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
1001 bool is_volatile) {
1002 for (RTCPPacketType type : types)
1003 SetFlag(type, is_volatile);
1004}
1005
sprang5e38c962016-12-01 05:18:09 -08001006bool RTCPSender::IsFlagPresent(uint32_t type) const {
Erik Språng242e22b2015-05-11 10:17:43 +02001007 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
1008}
1009
sprang5e38c962016-12-01 05:18:09 -08001010bool RTCPSender::ConsumeFlag(uint32_t type, bool forced) {
Erik Språng242e22b2015-05-11 10:17:43 +02001011 auto it = report_flags_.find(ReportFlag(type, false));
1012 if (it == report_flags_.end())
1013 return false;
1014 if (it->is_volatile || forced)
1015 report_flags_.erase((it));
1016 return true;
1017}
1018
1019bool RTCPSender::AllVolatileFlagsConsumed() const {
1020 for (const ReportFlag& flag : report_flags_) {
1021 if (flag.is_volatile)
1022 return false;
1023 }
1024 return true;
1025}
1026
sprang5e38c962016-12-01 05:18:09 -08001027void RTCPSender::SetVideoBitrateAllocation(const BitrateAllocation& bitrate) {
1028 rtc::CritScope lock(&critical_section_rtcp_sender_);
1029 video_bitrate_allocation_.emplace(bitrate);
1030 SetFlag(kRtcpAnyExtendedReports, true);
1031}
1032
sprang233bd872015-09-08 13:25:16 -07001033bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
sprang233bd872015-09-08 13:25:16 -07001034 class Sender : public rtcp::RtcpPacket::PacketReadyCallback {
1035 public:
terelius429c3452016-01-21 05:42:04 -08001036 Sender(Transport* transport, RtcEventLog* event_log)
1037 : transport_(transport), event_log_(event_log), send_failure_(false) {}
sprang233bd872015-09-08 13:25:16 -07001038
1039 void OnPacketReady(uint8_t* data, size_t length) override {
terelius429c3452016-01-21 05:42:04 -08001040 if (transport_->SendRtcp(data, length)) {
1041 if (event_log_) {
1042 event_log_->LogRtcpPacket(kOutgoingPacket, MediaType::ANY, data,
1043 length);
1044 }
1045 } else {
sprang233bd872015-09-08 13:25:16 -07001046 send_failure_ = true;
terelius429c3452016-01-21 05:42:04 -08001047 }
sprang233bd872015-09-08 13:25:16 -07001048 }
1049
1050 Transport* const transport_;
terelius429c3452016-01-21 05:42:04 -08001051 RtcEventLog* const event_log_;
sprang233bd872015-09-08 13:25:16 -07001052 bool send_failure_;
terelius429c3452016-01-21 05:42:04 -08001053 // TODO(terelius): We would like to
1054 // RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(Sender);
1055 // but we can't because of an incorrect warning (C4822) in MVS 2013.
1056 } sender(transport_, event_log_);
sprang233bd872015-09-08 13:25:16 -07001057
kwiberg352444f2016-11-28 15:58:53 -08001058 RTC_DCHECK_LE(max_payload_length_, IP_PACKET_SIZE);
sprang233bd872015-09-08 13:25:16 -07001059 uint8_t buffer[IP_PACKET_SIZE];
danilchap41befce2016-03-30 11:11:51 -07001060 return packet.BuildExternalBuffer(buffer, max_payload_length_, &sender) &&
sprang233bd872015-09-08 13:25:16 -07001061 !sender.send_failure_;
1062}
1063
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001064} // namespace webrtc