blob: 4a509b001ea0db5d438268b6011a163096f6abee [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000011#include "webrtc/modules/rtp_rtcp/source/rtcp_sender.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
stefan@webrtc.org9354cc92012-06-07 08:10:14 +000013#include <string.h> // memcpy
niklase@google.com470e71d2011-07-07 08:21:25 +000014
Erik Språng61be2a42015-04-27 13:32:52 +020015#include "webrtc/base/checks.h"
kwiberg4485ffb2016-04-26 08:14:39 -070016#include "webrtc/base/constructormagic.h"
Peter Boströmebc0b4e2015-10-28 16:39:33 +010017#include "webrtc/base/logging.h"
tommie4f96502015-10-20 23:00:48 -070018#include "webrtc/base/trace_event.h"
terelius429c3452016-01-21 05:42:04 -080019#include "webrtc/call.h"
20#include "webrtc/call/rtc_event_log.h"
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000021#include "webrtc/common_types.h"
danilchap0219c9b2015-11-18 05:56:53 -080022#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/app.h"
danilchap50c51362015-11-22 09:03:11 -080023#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/bye.h"
danilchap2f7dea12016-01-13 02:03:04 -080024#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/compound_packet.h"
Danil Chapovalov256e5b22016-01-15 14:16:24 +010025#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_reports.h"
Danil Chapovalov5679da12016-01-15 13:19:53 +010026#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/fir.h"
danilchapa8890a52015-12-22 03:43:04 -080027#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/nack.h"
danilchapf8385ad2015-11-27 05:36:09 -080028#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/pli.h"
Danil Chapovalov97f7e132015-12-04 16:13:30 +010029#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
Danil Chapovalova5eba6c2016-01-15 12:40:15 +010030#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/remb.h"
Danil Chapovalov2c132972016-01-15 15:21:21 +010031#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rpsi.h"
Danil Chapovalov1567d0b2016-01-15 17:34:27 +010032#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sdes.h"
danilchap34ed2b92016-01-18 02:43:32 -080033#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sender_report.h"
danilchap92e677a2016-01-12 10:04:52 -080034#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sli.h"
danilchapef3d8052016-01-11 03:31:08 -080035#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbn.h"
danilchap7e8145f2016-01-11 11:49:19 -080036#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbr.h"
sprang233bd872015-09-08 13:25:16 -070037#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
tommie4f96502015-10-20 23:00:48 -070038#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000039
niklase@google.com470e71d2011-07-07 08:21:25 +000040namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000041
Erik Språng61be2a42015-04-27 13:32:52 +020042NACKStringBuilder::NACKStringBuilder()
danilchap162abd32015-12-10 02:39:40 -080043 : stream_(""), count_(0), prevNack_(0), consecutive_(false) {}
edjee@google.com79b02892013-04-04 19:43:34 +000044
pbos@webrtc.orgf3e4cee2013-07-31 15:17:19 +000045NACKStringBuilder::~NACKStringBuilder() {}
46
danilchap162abd32015-12-10 02:39:40 -080047void NACKStringBuilder::PushNACK(uint16_t nack) {
Erik Språng242e22b2015-05-11 10:17:43 +020048 if (count_ == 0) {
49 stream_ << nack;
50 } else if (nack == prevNack_ + 1) {
51 consecutive_ = true;
Erik Språng61be2a42015-04-27 13:32:52 +020052 } else {
Erik Språng242e22b2015-05-11 10:17:43 +020053 if (consecutive_) {
54 stream_ << "-" << prevNack_;
55 consecutive_ = false;
edjee@google.com79b02892013-04-04 19:43:34 +000056 }
Erik Språng242e22b2015-05-11 10:17:43 +020057 stream_ << "," << nack;
Erik Språng61be2a42015-04-27 13:32:52 +020058 }
Erik Språng242e22b2015-05-11 10:17:43 +020059 count_++;
60 prevNack_ = nack;
edjee@google.com79b02892013-04-04 19:43:34 +000061}
62
Erik Språng61be2a42015-04-27 13:32:52 +020063std::string NACKStringBuilder::GetResult() {
Erik Språng242e22b2015-05-11 10:17:43 +020064 if (consecutive_) {
65 stream_ << "-" << prevNack_;
66 consecutive_ = false;
Erik Språng61be2a42015-04-27 13:32:52 +020067 }
Erik Språng242e22b2015-05-11 10:17:43 +020068 return stream_.str();
edjee@google.com79b02892013-04-04 19:43:34 +000069}
70
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000071RTCPSender::FeedbackState::FeedbackState()
72 : send_payload_type(0),
73 frequency_hz(0),
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +000074 packets_sent(0),
75 media_bytes_sent(0),
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000076 send_bitrate(0),
77 last_rr_ntp_secs(0),
78 last_rr_ntp_frac(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000079 remote_sr(0),
Erik Språng61be2a42015-04-27 13:32:52 +020080 has_last_xr_rr(false),
danilchap162abd32015-12-10 02:39:40 -080081 module(nullptr) {}
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000082
danilchap2f7dea12016-01-13 02:03:04 -080083class PacketContainer : public rtcp::CompoundPacket,
Erik Språngf7c57762015-12-04 10:40:35 +010084 public rtcp::RtcpPacket::PacketReadyCallback {
85 public:
terelius429c3452016-01-21 05:42:04 -080086 PacketContainer(Transport* transport, RtcEventLog* event_log)
87 : transport_(transport), event_log_(event_log), bytes_sent_(0) {}
Erik Språngf7c57762015-12-04 10:40:35 +010088 virtual ~PacketContainer() {
89 for (RtcpPacket* packet : appended_packets_)
90 delete packet;
91 }
92
93 void OnPacketReady(uint8_t* data, size_t length) override {
terelius429c3452016-01-21 05:42:04 -080094 if (transport_->SendRtcp(data, length)) {
Erik Språngf7c57762015-12-04 10:40:35 +010095 bytes_sent_ += length;
terelius429c3452016-01-21 05:42:04 -080096 if (event_log_) {
97 event_log_->LogRtcpPacket(kOutgoingPacket, MediaType::ANY, data,
98 length);
99 }
100 }
Erik Språngf7c57762015-12-04 10:40:35 +0100101 }
102
danilchap41befce2016-03-30 11:11:51 -0700103 size_t SendPackets(size_t max_payload_length) {
104 RTC_DCHECK_LE(max_payload_length, static_cast<size_t>(IP_PACKET_SIZE));
105 uint8_t buffer[IP_PACKET_SIZE];
106 BuildExternalBuffer(buffer, max_payload_length, this);
Erik Språngf7c57762015-12-04 10:40:35 +0100107 return bytes_sent_;
108 }
109
110 private:
111 Transport* transport_;
terelius429c3452016-01-21 05:42:04 -0800112 RtcEventLog* const event_log_;
Erik Språngf7c57762015-12-04 10:40:35 +0100113 size_t bytes_sent_;
terelius429c3452016-01-21 05:42:04 -0800114
115 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(PacketContainer);
Erik Språngf7c57762015-12-04 10:40:35 +0100116};
117
118class RTCPSender::RtcpContext {
119 public:
Erik Språng242e22b2015-05-11 10:17:43 +0200120 RtcpContext(const FeedbackState& feedback_state,
121 int32_t nack_size,
122 const uint16_t* nack_list,
123 bool repeat,
124 uint64_t picture_id,
Erik Språngf7c57762015-12-04 10:40:35 +0100125 uint32_t ntp_sec,
danilchap56036ff2016-03-22 11:14:09 -0700126 uint32_t ntp_frac)
Erik Språngf7c57762015-12-04 10:40:35 +0100127 : feedback_state_(feedback_state),
128 nack_size_(nack_size),
129 nack_list_(nack_list),
130 repeat_(repeat),
131 picture_id_(picture_id),
132 ntp_sec_(ntp_sec),
danilchap56036ff2016-03-22 11:14:09 -0700133 ntp_frac_(ntp_frac) {}
Erik Språng242e22b2015-05-11 10:17:43 +0200134
Erik Språngf7c57762015-12-04 10:40:35 +0100135 const FeedbackState& feedback_state_;
136 const int32_t nack_size_;
137 const uint16_t* nack_list_;
138 const bool repeat_;
139 const uint64_t picture_id_;
140 const uint32_t ntp_sec_;
141 const uint32_t ntp_frac_;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200142};
143
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000144RTCPSender::RTCPSender(
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000145 bool audio,
146 Clock* clock,
147 ReceiveStatistics* receive_statistics,
sprang86fd9ed2015-09-29 04:45:43 -0700148 RtcpPacketTypeCounterObserver* packet_type_counter_observer,
terelius429c3452016-01-21 05:42:04 -0800149 RtcEventLog* event_log,
sprang86fd9ed2015-09-29 04:45:43 -0700150 Transport* outgoing_transport)
Peter Boströmac547a62015-09-17 23:03:57 +0200151 : audio_(audio),
Erik Språng242e22b2015-05-11 10:17:43 +0200152 clock_(clock),
danilchap47a740b2015-12-15 00:30:07 -0800153 random_(clock_->TimeInMicroseconds()),
pbosda903ea2015-10-02 02:36:56 -0700154 method_(RtcpMode::kOff),
terelius429c3452016-01-21 05:42:04 -0800155 event_log_(event_log),
sprang86fd9ed2015-09-29 04:45:43 -0700156 transport_(outgoing_transport),
Erik Språng242e22b2015-05-11 10:17:43 +0200157 using_nack_(false),
158 sending_(false),
159 remb_enabled_(false),
Erik Språng242e22b2015-05-11 10:17:43 +0200160 next_time_to_send_rtcp_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000161 start_timestamp_(0),
162 last_rtp_timestamp_(0),
163 last_frame_capture_time_ms_(-1),
Erik Språng242e22b2015-05-11 10:17:43 +0200164 ssrc_(0),
165 remote_ssrc_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000166 receive_statistics_(receive_statistics),
niklase@google.com470e71d2011-07-07 08:21:25 +0000167
Erik Språng242e22b2015-05-11 10:17:43 +0200168 sequence_number_fir_(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000169
Erik Språng242e22b2015-05-11 10:17:43 +0200170 remb_bitrate_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000171
Erik Språng242e22b2015-05-11 10:17:43 +0200172 tmmbr_help_(),
173 tmmbr_send_(0),
174 packet_oh_send_(0),
danilchap41befce2016-03-30 11:11:51 -0700175 max_payload_length_(IP_PACKET_SIZE - 28), // IPv4 + UDP by default.
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000176
Erik Språng242e22b2015-05-11 10:17:43 +0200177 app_sub_type_(0),
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200178 app_name_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200179 app_data_(nullptr),
180 app_length_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000181
Erik Språng242e22b2015-05-11 10:17:43 +0200182 xr_send_receiver_reference_time_enabled_(false),
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000183 packet_type_counter_observer_(packet_type_counter_observer) {
sprang86fd9ed2015-09-29 04:45:43 -0700184 RTC_DCHECK(transport_ != nullptr);
Erik Språng242e22b2015-05-11 10:17:43 +0200185
186 builders_[kRtcpSr] = &RTCPSender::BuildSR;
187 builders_[kRtcpRr] = &RTCPSender::BuildRR;
Erik Språng0ea42d32015-06-25 14:46:16 +0200188 builders_[kRtcpSdes] = &RTCPSender::BuildSDES;
Erik Språng242e22b2015-05-11 10:17:43 +0200189 builders_[kRtcpPli] = &RTCPSender::BuildPLI;
190 builders_[kRtcpFir] = &RTCPSender::BuildFIR;
191 builders_[kRtcpSli] = &RTCPSender::BuildSLI;
192 builders_[kRtcpRpsi] = &RTCPSender::BuildRPSI;
193 builders_[kRtcpRemb] = &RTCPSender::BuildREMB;
194 builders_[kRtcpBye] = &RTCPSender::BuildBYE;
195 builders_[kRtcpApp] = &RTCPSender::BuildAPP;
196 builders_[kRtcpTmmbr] = &RTCPSender::BuildTMMBR;
197 builders_[kRtcpTmmbn] = &RTCPSender::BuildTMMBN;
198 builders_[kRtcpNack] = &RTCPSender::BuildNACK;
199 builders_[kRtcpXrVoipMetric] = &RTCPSender::BuildVoIPMetric;
200 builders_[kRtcpXrReceiverReferenceTime] =
201 &RTCPSender::BuildReceiverReferenceTime;
202 builders_[kRtcpXrDlrrReportBlock] = &RTCPSender::BuildDlrr;
niklase@google.com470e71d2011-07-07 08:21:25 +0000203}
204
danilchap162abd32015-12-10 02:39:40 -0800205RTCPSender::~RTCPSender() {}
niklase@google.com470e71d2011-07-07 08:21:25 +0000206
pbosda903ea2015-10-02 02:36:56 -0700207RtcpMode RTCPSender::Status() const {
danilchap56036ff2016-03-22 11:14:09 -0700208 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200209 return method_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000210}
211
skvlad1c392cc2016-04-01 14:46:44 -0700212void RTCPSender::SetRTCPStatus(RtcpMode new_method) {
danilchap56036ff2016-03-22 11:14:09 -0700213 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000214
skvlad1c392cc2016-04-01 14:46:44 -0700215 if (method_ == RtcpMode::kOff && new_method != RtcpMode::kOff) {
216 // When switching on, reschedule the next packet
217 next_time_to_send_rtcp_ =
Erik Språng242e22b2015-05-11 10:17:43 +0200218 clock_->TimeInMilliseconds() +
219 (audio_ ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
skvlad1c392cc2016-04-01 14:46:44 -0700220 }
221 method_ = new_method;
niklase@google.com470e71d2011-07-07 08:21:25 +0000222}
223
Erik Språng61be2a42015-04-27 13:32:52 +0200224bool RTCPSender::Sending() const {
danilchap56036ff2016-03-22 11:14:09 -0700225 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200226 return sending_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000227}
228
Erik Språng61be2a42015-04-27 13:32:52 +0200229int32_t RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
230 bool sending) {
231 bool sendRTCPBye = false;
232 {
danilchap56036ff2016-03-22 11:14:09 -0700233 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000234
pbosda903ea2015-10-02 02:36:56 -0700235 if (method_ != RtcpMode::kOff) {
Erik Språng242e22b2015-05-11 10:17:43 +0200236 if (sending == false && sending_ == true) {
Erik Språng61be2a42015-04-27 13:32:52 +0200237 // Trigger RTCP bye
238 sendRTCPBye = true;
239 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000240 }
Erik Språng242e22b2015-05-11 10:17:43 +0200241 sending_ = sending;
Erik Språng61be2a42015-04-27 13:32:52 +0200242 }
243 if (sendRTCPBye)
244 return SendRTCP(feedback_state, kRtcpBye);
245 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000246}
247
Erik Språng61be2a42015-04-27 13:32:52 +0200248bool RTCPSender::REMB() const {
danilchap56036ff2016-03-22 11:14:09 -0700249 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200250 return remb_enabled_;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000251}
252
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000253void RTCPSender::SetREMBStatus(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700254 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200255 remb_enabled_ = enable;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000256}
257
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000258void RTCPSender::SetREMBData(uint32_t bitrate,
259 const std::vector<uint32_t>& ssrcs) {
danilchap56036ff2016-03-22 11:14:09 -0700260 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200261 remb_bitrate_ = bitrate;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000262 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000263
Erik Språng242e22b2015-05-11 10:17:43 +0200264 if (remb_enabled_)
265 SetFlag(kRtcpRemb, false);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000266 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
267 // throttled by the caller.
Erik Språng242e22b2015-05-11 10:17:43 +0200268 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000269}
270
Erik Språng61be2a42015-04-27 13:32:52 +0200271bool RTCPSender::TMMBR() const {
danilchap56036ff2016-03-22 11:14:09 -0700272 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200273 return IsFlagPresent(RTCPPacketType::kRtcpTmmbr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000274}
275
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000276void RTCPSender::SetTMMBRStatus(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700277 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200278 if (enable) {
279 SetFlag(RTCPPacketType::kRtcpTmmbr, false);
280 } else {
281 ConsumeFlag(RTCPPacketType::kRtcpTmmbr, true);
282 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000283}
284
danilchap41befce2016-03-30 11:11:51 -0700285void RTCPSender::SetMaxPayloadLength(size_t max_payload_length) {
286 max_payload_length_ = max_payload_length;
287}
288
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000289void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
danilchap56036ff2016-03-22 11:14:09 -0700290 rtc::CritScope lock(&critical_section_rtcp_sender_);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000291 start_timestamp_ = start_timestamp;
292}
293
294void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
295 int64_t capture_time_ms) {
danilchap56036ff2016-03-22 11:14:09 -0700296 rtc::CritScope lock(&critical_section_rtcp_sender_);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000297 last_rtp_timestamp_ = rtp_timestamp;
298 if (capture_time_ms < 0) {
299 // We don't currently get a capture time from VoiceEngine.
Erik Språng242e22b2015-05-11 10:17:43 +0200300 last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000301 } else {
302 last_frame_capture_time_ms_ = capture_time_ms;
303 }
304}
305
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000306void RTCPSender::SetSSRC(uint32_t ssrc) {
danilchap56036ff2016-03-22 11:14:09 -0700307 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000308
Erik Språng242e22b2015-05-11 10:17:43 +0200309 if (ssrc_ != 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200310 // not first SetSSRC, probably due to a collision
311 // schedule a new RTCP report
312 // make sure that we send a RTP packet
Erik Språng242e22b2015-05-11 10:17:43 +0200313 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
Erik Språng61be2a42015-04-27 13:32:52 +0200314 }
Erik Språng242e22b2015-05-11 10:17:43 +0200315 ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000316}
317
Erik Språng61be2a42015-04-27 13:32:52 +0200318void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
danilchap56036ff2016-03-22 11:14:09 -0700319 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200320 remote_ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000321}
322
Peter Boström9ba52f82015-06-01 14:12:28 +0200323int32_t RTCPSender::SetCNAME(const char* c_name) {
324 if (!c_name)
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000325 return -1;
326
henrikg91d6ede2015-09-17 00:24:34 -0700327 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
danilchap56036ff2016-03-22 11:14:09 -0700328 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200329 cname_ = c_name;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000330 return 0;
331}
332
Erik Språng0ea42d32015-06-25 14:46:16 +0200333int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC, const char* c_name) {
danilchap56036ff2016-03-22 11:14:09 -0700334 RTC_DCHECK(c_name);
henrikg91d6ede2015-09-17 00:24:34 -0700335 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
danilchap56036ff2016-03-22 11:14:09 -0700336 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200337 if (csrc_cnames_.size() >= kRtpCsrcSize)
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000338 return -1;
Erik Språng0ea42d32015-06-25 14:46:16 +0200339
340 csrc_cnames_[SSRC] = c_name;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000341 return 0;
342}
343
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000344int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
danilchap56036ff2016-03-22 11:14:09 -0700345 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200346 auto it = csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000347
Erik Språng242e22b2015-05-11 10:17:43 +0200348 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000349 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200350
Erik Språng242e22b2015-05-11 10:17:43 +0200351 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000352 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000353}
354
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000355bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
danilchap162abd32015-12-10 02:39:40 -0800356 /*
357 For audio we use a fix 5 sec interval
niklase@google.com470e71d2011-07-07 08:21:25 +0000358
danilchap162abd32015-12-10 02:39:40 -0800359 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
360 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
361 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000362
363
danilchap162abd32015-12-10 02:39:40 -0800364 From RFC 3550
niklase@google.com470e71d2011-07-07 08:21:25 +0000365
danilchap162abd32015-12-10 02:39:40 -0800366 MAX RTCP BW is 5% if the session BW
367 A send report is approximately 65 bytes inc CNAME
368 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000369
danilchap162abd32015-12-10 02:39:40 -0800370 The RECOMMENDED value for the reduced minimum in seconds is 360
371 divided by the session bandwidth in kilobits/second. This minimum
372 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
niklase@google.com470e71d2011-07-07 08:21:25 +0000373
danilchap162abd32015-12-10 02:39:40 -0800374 If the participant has not yet sent an RTCP packet (the variable
375 initial is true), the constant Tmin is set to 2.5 seconds, else it
376 is set to 5 seconds.
niklase@google.com470e71d2011-07-07 08:21:25 +0000377
danilchap162abd32015-12-10 02:39:40 -0800378 The interval between RTCP packets is varied randomly over the
379 range [0.5,1.5] times the calculated interval to avoid unintended
380 synchronization of all participants
niklase@google.com470e71d2011-07-07 08:21:25 +0000381
danilchap162abd32015-12-10 02:39:40 -0800382 if we send
383 If the participant is a sender (we_sent true), the constant C is
384 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
385 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
386 number of senders.
niklase@google.com470e71d2011-07-07 08:21:25 +0000387
danilchap162abd32015-12-10 02:39:40 -0800388 if we receive only
389 If we_sent is not true, the constant C is set
390 to the average RTCP packet size divided by 75% of the RTCP
391 bandwidth. The constant n is set to the number of receivers
392 (members - senders). If the number of senders is greater than
393 25%, senders and receivers are treated together.
niklase@google.com470e71d2011-07-07 08:21:25 +0000394
danilchap162abd32015-12-10 02:39:40 -0800395 reconsideration NOT required for peer-to-peer
396 "timer reconsideration" is
397 employed. This algorithm implements a simple back-off mechanism
398 which causes users to hold back RTCP packet transmission if the
399 group sizes are increasing.
niklase@google.com470e71d2011-07-07 08:21:25 +0000400
danilchap162abd32015-12-10 02:39:40 -0800401 n = number of members
402 C = avg_size/(rtcpBW/4)
niklase@google.com470e71d2011-07-07 08:21:25 +0000403
danilchap162abd32015-12-10 02:39:40 -0800404 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
niklase@google.com470e71d2011-07-07 08:21:25 +0000405
danilchap162abd32015-12-10 02:39:40 -0800406 4. The calculated interval T is set to a number uniformly distributed
407 between 0.5 and 1.5 times the deterministic calculated interval.
niklase@google.com470e71d2011-07-07 08:21:25 +0000408
danilchap162abd32015-12-10 02:39:40 -0800409 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
410 for the fact that the timer reconsideration algorithm converges to
411 a value of the RTCP bandwidth below the intended average
412 */
niklase@google.com470e71d2011-07-07 08:21:25 +0000413
Erik Språng242e22b2015-05-11 10:17:43 +0200414 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000415
danilchap56036ff2016-03-22 11:14:09 -0700416 rtc::CritScope lock(&critical_section_rtcp_sender_);
xians@webrtc.org8738d272011-11-25 13:43:53 +0000417
pbosda903ea2015-10-02 02:36:56 -0700418 if (method_ == RtcpMode::kOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000419 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000420
Erik Språng242e22b2015-05-11 10:17:43 +0200421 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200422 // for video key-frames we want to send the RTCP before the large key-frame
423 // if we have a 100 ms margin
424 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
425 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000426
Erik Språng242e22b2015-05-11 10:17:43 +0200427 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200428 return true;
429 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200430 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200431 // wrap
432 return true;
433 }
434 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000435}
436
danilchap56036ff2016-03-22 11:14:09 -0700437std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSR(const RtcpContext& ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200438 // The timestamp of this RTCP packet should be estimated as the timestamp of
439 // the frame being captured at this moment. We are calculating that
440 // timestamp as the last frame's timestamp + the time since the last frame
441 // was captured.
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200442 uint32_t rtp_timestamp =
443 start_timestamp_ + last_rtp_timestamp_ +
444 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) *
Erik Språngf7c57762015-12-04 10:40:35 +0100445 (ctx.feedback_state_.frequency_hz / 1000);
niklase@google.com470e71d2011-07-07 08:21:25 +0000446
Erik Språngf7c57762015-12-04 10:40:35 +0100447 rtcp::SenderReport* report = new rtcp::SenderReport();
448 report->From(ssrc_);
danilchap34ed2b92016-01-18 02:43:32 -0800449 report->WithNtp(NtpTime(ctx.ntp_sec_, ctx.ntp_frac_));
Erik Språngf7c57762015-12-04 10:40:35 +0100450 report->WithRtpTimestamp(rtp_timestamp);
451 report->WithPacketCount(ctx.feedback_state_.packets_sent);
452 report->WithOctetCount(ctx.feedback_state_.media_bytes_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000453
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200454 for (auto it : report_blocks_)
Erik Språngf7c57762015-12-04 10:40:35 +0100455 report->WithReportBlock(it.second);
niklase@google.com470e71d2011-07-07 08:21:25 +0000456
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200457 report_blocks_.clear();
Erik Språngf7c57762015-12-04 10:40:35 +0100458
danilchap56036ff2016-03-22 11:14:09 -0700459 return std::unique_ptr<rtcp::RtcpPacket>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000460}
461
danilchap56036ff2016-03-22 11:14:09 -0700462std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSDES(
Erik Språngf7c57762015-12-04 10:40:35 +0100463 const RtcpContext& ctx) {
Erik Språng0ea42d32015-06-25 14:46:16 +0200464 size_t length_cname = cname_.length();
henrikg91d6ede2015-09-17 00:24:34 -0700465 RTC_CHECK_LT(length_cname, static_cast<size_t>(RTCP_CNAME_SIZE));
niklase@google.com470e71d2011-07-07 08:21:25 +0000466
Erik Språngf7c57762015-12-04 10:40:35 +0100467 rtcp::Sdes* sdes = new rtcp::Sdes();
468 sdes->WithCName(ssrc_, cname_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200469
470 for (const auto it : csrc_cnames_)
Erik Språngf7c57762015-12-04 10:40:35 +0100471 sdes->WithCName(it.first, it.second);
Erik Språng0ea42d32015-06-25 14:46:16 +0200472
danilchap56036ff2016-03-22 11:14:09 -0700473 return std::unique_ptr<rtcp::RtcpPacket>(sdes);
niklase@google.com470e71d2011-07-07 08:21:25 +0000474}
475
danilchap56036ff2016-03-22 11:14:09 -0700476std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildRR(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100477 rtcp::ReceiverReport* report = new rtcp::ReceiverReport();
478 report->From(ssrc_);
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200479 for (auto it : report_blocks_)
Erik Språngf7c57762015-12-04 10:40:35 +0100480 report->WithReportBlock(it.second);
Erik Språng61be2a42015-04-27 13:32:52 +0200481
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200482 report_blocks_.clear();
danilchap56036ff2016-03-22 11:14:09 -0700483 return std::unique_ptr<rtcp::RtcpPacket>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000484}
485
danilchap56036ff2016-03-22 11:14:09 -0700486std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildPLI(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100487 rtcp::Pli* pli = new rtcp::Pli();
488 pli->From(ssrc_);
489 pli->To(remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200490
Erik Språng242e22b2015-05-11 10:17:43 +0200491 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
492 "RTCPSender::PLI");
493 ++packet_type_counter_.pli_packets;
494 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
495 ssrc_, packet_type_counter_.pli_packets);
496
danilchap56036ff2016-03-22 11:14:09 -0700497 return std::unique_ptr<rtcp::RtcpPacket>(pli);
Erik Språng61be2a42015-04-27 13:32:52 +0200498}
499
danilchap56036ff2016-03-22 11:14:09 -0700500std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildFIR(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100501 if (!ctx.repeat_)
sprang62dae192015-08-05 02:35:35 -0700502 ++sequence_number_fir_; // Do not increase if repetition.
niklase@google.com470e71d2011-07-07 08:21:25 +0000503
Erik Språngf7c57762015-12-04 10:40:35 +0100504 rtcp::Fir* fir = new rtcp::Fir();
505 fir->From(ssrc_);
Danil Chapovalov32e590e2016-01-22 11:04:56 +0100506 fir->WithRequestTo(remote_ssrc_, sequence_number_fir_);
Erik Språng242e22b2015-05-11 10:17:43 +0200507
508 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
509 "RTCPSender::FIR");
510 ++packet_type_counter_.fir_packets;
511 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
512 ssrc_, packet_type_counter_.fir_packets);
513
danilchap56036ff2016-03-22 11:14:09 -0700514 return std::unique_ptr<rtcp::RtcpPacket>(fir);
niklase@google.com470e71d2011-07-07 08:21:25 +0000515}
516
517/*
518 0 1 2 3
519 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
520 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
521 | First | Number | PictureID |
522 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
523*/
danilchap56036ff2016-03-22 11:14:09 -0700524std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSLI(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100525 rtcp::Sli* sli = new rtcp::Sli();
526 sli->From(ssrc_);
527 sli->To(remote_ssrc_);
sprang0365a272015-08-11 01:02:37 -0700528 // Crop picture id to 6 least significant bits.
Erik Språngf7c57762015-12-04 10:40:35 +0100529 sli->WithPictureId(ctx.picture_id_ & 0x3F);
sprang0365a272015-08-11 01:02:37 -0700530
danilchap56036ff2016-03-22 11:14:09 -0700531 return std::unique_ptr<rtcp::RtcpPacket>(sli);
niklase@google.com470e71d2011-07-07 08:21:25 +0000532}
533
534/*
535 0 1 2 3
536 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
537 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
538 | PB |0| Payload Type| Native RPSI bit string |
539 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
540 | defined per codec ... | Padding (0) |
541 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
542*/
543/*
544* Note: not generic made for VP8
545*/
danilchap56036ff2016-03-22 11:14:09 -0700546std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildRPSI(
Erik Språngf7c57762015-12-04 10:40:35 +0100547 const RtcpContext& ctx) {
548 if (ctx.feedback_state_.send_payload_type == 0xFF)
549 return nullptr;
Erik Språng242e22b2015-05-11 10:17:43 +0200550
Erik Språngf7c57762015-12-04 10:40:35 +0100551 rtcp::Rpsi* rpsi = new rtcp::Rpsi();
552 rpsi->From(ssrc_);
553 rpsi->To(remote_ssrc_);
554 rpsi->WithPayloadType(ctx.feedback_state_.send_payload_type);
555 rpsi->WithPictureId(ctx.picture_id_);
sprangcf7f54d2015-08-13 04:37:42 -0700556
danilchap56036ff2016-03-22 11:14:09 -0700557 return std::unique_ptr<rtcp::RtcpPacket>(rpsi);
niklase@google.com470e71d2011-07-07 08:21:25 +0000558}
559
danilchap56036ff2016-03-22 11:14:09 -0700560std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildREMB(
Erik Språngf7c57762015-12-04 10:40:35 +0100561 const RtcpContext& ctx) {
562 rtcp::Remb* remb = new rtcp::Remb();
563 remb->From(ssrc_);
sprangdd4edc52015-08-21 04:21:51 -0700564 for (uint32_t ssrc : remb_ssrcs_)
Erik Språngf7c57762015-12-04 10:40:35 +0100565 remb->AppliesTo(ssrc);
566 remb->WithBitrateBps(remb_bitrate_);
Erik Språng61be2a42015-04-27 13:32:52 +0200567
Erik Språng242e22b2015-05-11 10:17:43 +0200568 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
569 "RTCPSender::REMB");
570
danilchap56036ff2016-03-22 11:14:09 -0700571 return std::unique_ptr<rtcp::RtcpPacket>(remb);
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000572}
573
Erik Språng61be2a42015-04-27 13:32:52 +0200574void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
danilchap56036ff2016-03-22 11:14:09 -0700575 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200576 tmmbr_send_ = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000577}
578
danilchap56036ff2016-03-22 11:14:09 -0700579std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBR(
Erik Språngf7c57762015-12-04 10:40:35 +0100580 const RtcpContext& ctx) {
581 if (ctx.feedback_state_.module == nullptr)
582 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200583 // Before sending the TMMBR check the received TMMBN, only an owner is
584 // allowed to raise the bitrate:
585 // * If the sender is an owner of the TMMBN -> send TMMBR
586 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000587
Erik Språng61be2a42015-04-27 13:32:52 +0200588 // get current bounding set from RTCP receiver
589 bool tmmbrOwner = false;
590 // store in candidateSet, allocates one extra slot
Erik Språng242e22b2015-05-11 10:17:43 +0200591 TMMBRSet* candidateSet = tmmbr_help_.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000592
Erik Språng242e22b2015-05-11 10:17:43 +0200593 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
594 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
Erik Språng61be2a42015-04-27 13:32:52 +0200595 // since RTCPreceiver is not doing the reverse we should be fine
596 int32_t lengthOfBoundingSet =
danilchap6db6cdc2015-12-15 02:54:47 -0800597 ctx.feedback_state_.module->BoundingSet(&tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +0000598
Erik Språng61be2a42015-04-27 13:32:52 +0200599 if (lengthOfBoundingSet > 0) {
600 for (int32_t i = 0; i < lengthOfBoundingSet; i++) {
Erik Språng242e22b2015-05-11 10:17:43 +0200601 if (candidateSet->Tmmbr(i) == tmmbr_send_ &&
602 candidateSet->PacketOH(i) == packet_oh_send_) {
Erik Språngf7c57762015-12-04 10:40:35 +0100603 // Do not send the same tuple.
604 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200605 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000606 }
Erik Språng61be2a42015-04-27 13:32:52 +0200607 if (!tmmbrOwner) {
608 // use received bounding set as candidate set
609 // add current tuple
Erik Språng242e22b2015-05-11 10:17:43 +0200610 candidateSet->SetEntry(lengthOfBoundingSet, tmmbr_send_, packet_oh_send_,
611 ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200612 int numCandidates = lengthOfBoundingSet + 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000613
Erik Språng61be2a42015-04-27 13:32:52 +0200614 // find bounding set
Erik Språngf7c57762015-12-04 10:40:35 +0100615 TMMBRSet* boundingSet = nullptr;
Erik Språng242e22b2015-05-11 10:17:43 +0200616 int numBoundingSet = tmmbr_help_.FindTMMBRBoundingSet(boundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200617 if (numBoundingSet > 0 || numBoundingSet <= numCandidates)
Erik Språng242e22b2015-05-11 10:17:43 +0200618 tmmbrOwner = tmmbr_help_.IsOwner(ssrc_, numBoundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200619 if (!tmmbrOwner) {
Erik Språngf7c57762015-12-04 10:40:35 +0100620 // Did not enter bounding set, no meaning to send this request.
621 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200622 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000623 }
Erik Språng61be2a42015-04-27 13:32:52 +0200624 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000625
Erik Språngf7c57762015-12-04 10:40:35 +0100626 if (!tmmbr_send_)
627 return nullptr;
sprang81a3e602015-08-21 05:30:11 -0700628
Erik Språngf7c57762015-12-04 10:40:35 +0100629 rtcp::Tmmbr* tmmbr = new rtcp::Tmmbr();
630 tmmbr->From(ssrc_);
danilchapf174e3a2016-02-05 04:56:36 -0800631 rtcp::TmmbItem request;
632 request.set_ssrc(remote_ssrc_);
633 request.set_bitrate_bps(tmmbr_send_ * 1000);
634 request.set_packet_overhead(packet_oh_send_);
635 tmmbr->WithTmmbr(request);
Erik Språngf7c57762015-12-04 10:40:35 +0100636
danilchap56036ff2016-03-22 11:14:09 -0700637 return std::unique_ptr<rtcp::RtcpPacket>(tmmbr);
Erik Språng61be2a42015-04-27 13:32:52 +0200638}
639
danilchap56036ff2016-03-22 11:14:09 -0700640std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBN(
Erik Språngf7c57762015-12-04 10:40:35 +0100641 const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100642 rtcp::Tmmbn* tmmbn = new rtcp::Tmmbn();
643 tmmbn->From(ssrc_);
danilchap6eaa3a42016-05-09 10:59:50 -0700644 for (const rtcp::TmmbItem& tmmbr : tmmbn_to_send_) {
645 if (tmmbr.bitrate_bps() > 0) {
646 tmmbn->WithTmmbr(tmmbr);
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000647 }
Erik Språng61be2a42015-04-27 13:32:52 +0200648 }
sprangd83df502015-08-27 01:05:08 -0700649
danilchap56036ff2016-03-22 11:14:09 -0700650 return std::unique_ptr<rtcp::RtcpPacket>(tmmbn);
niklase@google.com470e71d2011-07-07 08:21:25 +0000651}
652
danilchap56036ff2016-03-22 11:14:09 -0700653std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildAPP(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100654 rtcp::App* app = new rtcp::App();
655 app->From(ssrc_);
656 app->WithSubType(app_sub_type_);
657 app->WithName(app_name_);
658 app->WithData(app_data_.get(), app_length_);
Erik Språng521875a2015-09-01 10:11:16 +0200659
danilchap56036ff2016-03-22 11:14:09 -0700660 return std::unique_ptr<rtcp::RtcpPacket>(app);
Erik Språng61be2a42015-04-27 13:32:52 +0200661}
662
danilchap56036ff2016-03-22 11:14:09 -0700663std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildNACK(
Erik Språngf7c57762015-12-04 10:40:35 +0100664 const RtcpContext& ctx) {
665 rtcp::Nack* nack = new rtcp::Nack();
666 nack->From(ssrc_);
667 nack->To(remote_ssrc_);
668 nack->WithList(ctx.nack_list_, ctx.nack_size_);
Erik Språng61be2a42015-04-27 13:32:52 +0200669
670 // Report stats.
671 NACKStringBuilder stringBuilder;
Erik Språngf7c57762015-12-04 10:40:35 +0100672 for (int idx = 0; idx < ctx.nack_size_; ++idx) {
673 stringBuilder.PushNACK(ctx.nack_list_[idx]);
674 nack_stats_.ReportRequest(ctx.nack_list_[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +0200675 }
Erik Språng61be2a42015-04-27 13:32:52 +0200676 packet_type_counter_.nack_requests = nack_stats_.requests();
677 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +0200678
679 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
680 "RTCPSender::NACK", "nacks",
681 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
682 ++packet_type_counter_.nack_packets;
683 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
684 ssrc_, packet_type_counter_.nack_packets);
685
danilchap56036ff2016-03-22 11:14:09 -0700686 return std::unique_ptr<rtcp::RtcpPacket>(nack);
Erik Språng61be2a42015-04-27 13:32:52 +0200687}
688
danilchap56036ff2016-03-22 11:14:09 -0700689std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildBYE(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100690 rtcp::Bye* bye = new rtcp::Bye();
691 bye->From(ssrc_);
sprangd8ee4f92015-08-24 03:25:19 -0700692 for (uint32_t csrc : csrcs_)
Erik Språngf7c57762015-12-04 10:40:35 +0100693 bye->WithCsrc(csrc);
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
danilchap56036ff2016-03-22 11:14:09 -0700698std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildReceiverReferenceTime(
Erik Språngf7c57762015-12-04 10:40:35 +0100699 const RtcpContext& ctx) {
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000700
Danil Chapovalov256e5b22016-01-15 14:16:24 +0100701 rtcp::ExtendedReports* xr = new rtcp::ExtendedReports();
Erik Språngf7c57762015-12-04 10:40:35 +0100702 xr->From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000703
Erik Språngca28fdc2015-08-31 14:00:50 +0200704 rtcp::Rrtr rrtr;
Danil Chapovalovfc47ed62015-12-07 14:46:35 +0100705 rrtr.WithNtp(NtpTime(ctx.ntp_sec_, ctx.ntp_frac_));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000706
danilchapde138822016-01-29 11:26:14 -0800707 xr->WithRrtr(rrtr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000708
Erik Språngca28fdc2015-08-31 14:00:50 +0200709 // TODO(sprang): Merge XR report sending to contain all of RRTR, DLRR, VOIP?
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000710
danilchap56036ff2016-03-22 11:14:09 -0700711 return std::unique_ptr<rtcp::RtcpPacket>(xr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000712}
713
danilchap56036ff2016-03-22 11:14:09 -0700714std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildDlrr(
Erik Språngf7c57762015-12-04 10:40:35 +0100715 const RtcpContext& ctx) {
Danil Chapovalov256e5b22016-01-15 14:16:24 +0100716 rtcp::ExtendedReports* xr = new rtcp::ExtendedReports();
Erik Språngf7c57762015-12-04 10:40:35 +0100717 xr->From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000718
Erik Språngca28fdc2015-08-31 14:00:50 +0200719 rtcp::Dlrr dlrr;
Erik Språngf7c57762015-12-04 10:40:35 +0100720 const RtcpReceiveTimeInfo& info = ctx.feedback_state_.last_xr_rr;
Erik Språngca28fdc2015-08-31 14:00:50 +0200721 dlrr.WithDlrrItem(info.sourceSSRC, info.lastRR, info.delaySinceLastRR);
722
danilchapde138822016-01-29 11:26:14 -0800723 xr->WithDlrr(dlrr);
Erik Språngca28fdc2015-08-31 14:00:50 +0200724
danilchap56036ff2016-03-22 11:14:09 -0700725 return std::unique_ptr<rtcp::RtcpPacket>(xr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000726}
727
Erik Språng242e22b2015-05-11 10:17:43 +0200728// TODO(sprang): Add a unit test for this, or remove if the code isn't used.
danilchap56036ff2016-03-22 11:14:09 -0700729std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildVoIPMetric(
Erik Språngf7c57762015-12-04 10:40:35 +0100730 const RtcpContext& context) {
Danil Chapovalov256e5b22016-01-15 14:16:24 +0100731 rtcp::ExtendedReports* xr = new rtcp::ExtendedReports();
Erik Språngf7c57762015-12-04 10:40:35 +0100732 xr->From(ssrc_);
Erik Språngca28fdc2015-08-31 14:00:50 +0200733
734 rtcp::VoipMetric voip;
735 voip.To(remote_ssrc_);
danilchap91941ae2015-12-15 07:06:36 -0800736 voip.WithVoipMetric(xr_voip_metric_);
Erik Språngca28fdc2015-08-31 14:00:50 +0200737
danilchapde138822016-01-29 11:26:14 -0800738 xr->WithVoipMetric(voip);
Erik Språngca28fdc2015-08-31 14:00:50 +0200739
danilchap56036ff2016-03-22 11:14:09 -0700740 return std::unique_ptr<rtcp::RtcpPacket>(xr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000741}
742
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000743int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200744 RTCPPacketType packetType,
745 int32_t nack_size,
746 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000747 bool repeat,
748 uint64_t pictureID) {
Erik Språng242e22b2015-05-11 10:17:43 +0200749 return SendCompoundRTCP(
750 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
751 nack_size, nack_list, repeat, pictureID);
752}
753
754int32_t RTCPSender::SendCompoundRTCP(
755 const FeedbackState& feedback_state,
Erik Språngf7c57762015-12-04 10:40:35 +0100756 const std::set<RTCPPacketType>& packet_types,
Erik Språng242e22b2015-05-11 10:17:43 +0200757 int32_t nack_size,
758 const uint16_t* nack_list,
759 bool repeat,
760 uint64_t pictureID) {
terelius429c3452016-01-21 05:42:04 -0800761 PacketContainer container(transport_, event_log_);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000762 {
danilchap56036ff2016-03-22 11:14:09 -0700763 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbosda903ea2015-10-02 02:36:56 -0700764 if (method_ == RtcpMode::kOff) {
Erik Språng61be2a42015-04-27 13:32:52 +0200765 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
766 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +0000767 }
Erik Språngf7c57762015-12-04 10:40:35 +0100768
769 // We need to send our NTP even if we haven't received any reports.
770 uint32_t ntp_sec;
771 uint32_t ntp_frac;
772 clock_->CurrentNtp(ntp_sec, ntp_frac);
773 RtcpContext context(feedback_state, nack_size, nack_list, repeat, pictureID,
danilchap56036ff2016-03-22 11:14:09 -0700774 ntp_sec, ntp_frac);
Erik Språngf7c57762015-12-04 10:40:35 +0100775
776 PrepareReport(packet_types, feedback_state);
777
danilchap56036ff2016-03-22 11:14:09 -0700778 std::unique_ptr<rtcp::RtcpPacket> packet_bye;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800779
Erik Språngf7c57762015-12-04 10:40:35 +0100780 auto it = report_flags_.begin();
781 while (it != report_flags_.end()) {
782 auto builder_it = builders_.find(it->type);
783 RTC_DCHECK(builder_it != builders_.end());
784 if (it->is_volatile) {
785 report_flags_.erase(it++);
786 } else {
787 ++it;
788 }
789
790 BuilderFunc func = builder_it->second;
danilchap56036ff2016-03-22 11:14:09 -0700791 std::unique_ptr<rtcp::RtcpPacket> packet = (this->*func)(context);
Erik Språngf7c57762015-12-04 10:40:35 +0100792 if (packet.get() == nullptr)
793 return -1;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800794 // If there is a BYE, don't append now - save it and append it
795 // at the end later.
796 if (builder_it->first == kRtcpBye) {
797 packet_bye = std::move(packet);
798 } else {
799 container.Append(packet.release());
800 }
801 }
802
803 // Append the BYE now at the end
804 if (packet_bye) {
805 container.Append(packet_bye.release());
Erik Språngf7c57762015-12-04 10:40:35 +0100806 }
807
808 if (packet_type_counter_observer_ != nullptr) {
809 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
810 remote_ssrc_, packet_type_counter_);
811 }
812
813 RTC_DCHECK(AllVolatileFlagsConsumed());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000814 }
Erik Språng61be2a42015-04-27 13:32:52 +0200815
danilchap41befce2016-03-30 11:11:51 -0700816 size_t bytes_sent = container.SendPackets(max_payload_length_);
Erik Språngf7c57762015-12-04 10:40:35 +0100817 return bytes_sent == 0 ? -1 : 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000818}
819
Erik Språngf7c57762015-12-04 10:40:35 +0100820void RTCPSender::PrepareReport(const std::set<RTCPPacketType>& packetTypes,
821 const FeedbackState& feedback_state) {
Erik Språng242e22b2015-05-11 10:17:43 +0200822 // Add all flags as volatile. Non volatile entries will not be overwritten
823 // and all new volatile flags added will be consumed by the end of this call.
824 SetFlags(packetTypes, true);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000825
Erik Språng61be2a42015-04-27 13:32:52 +0200826 if (packet_type_counter_.first_packet_time_ms == -1)
Erik Språng242e22b2015-05-11 10:17:43 +0200827 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språng61be2a42015-04-27 13:32:52 +0200828
Erik Språng242e22b2015-05-11 10:17:43 +0200829 bool generate_report;
830 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
831 // Report type already explicitly set, don't automatically populate.
832 generate_report = true;
henrikg91d6ede2015-09-17 00:24:34 -0700833 RTC_DCHECK(ConsumeFlag(kRtcpReport) == false);
Erik Språng242e22b2015-05-11 10:17:43 +0200834 } else {
835 generate_report =
pbosda903ea2015-10-02 02:36:56 -0700836 (ConsumeFlag(kRtcpReport) && method_ == RtcpMode::kReducedSize) ||
837 method_ == RtcpMode::kCompound;
Erik Språng242e22b2015-05-11 10:17:43 +0200838 if (generate_report)
839 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000840 }
841
Erik Språng0ea42d32015-06-25 14:46:16 +0200842 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
Erik Språng242e22b2015-05-11 10:17:43 +0200843 SetFlag(kRtcpSdes, true);
844
Erik Språng242e22b2015-05-11 10:17:43 +0200845 if (generate_report) {
846 if (!sending_ && xr_send_receiver_reference_time_enabled_)
847 SetFlag(kRtcpXrReceiverReferenceTime, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200848 if (feedback_state.has_last_xr_rr)
Erik Språng242e22b2015-05-11 10:17:43 +0200849 SetFlag(kRtcpXrDlrrReportBlock, true);
850
851 // generate next time to send an RTCP report
danilchap47a740b2015-12-15 00:30:07 -0800852 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000853
danilchap47a740b2015-12-15 00:30:07 -0800854 if (!audio_) {
Erik Språng242e22b2015-05-11 10:17:43 +0200855 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200856 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
857 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
858 if (send_bitrate_kbit != 0)
859 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000860 }
Erik Språng61be2a42015-04-27 13:32:52 +0200861 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
862 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
Erik Språng61be2a42015-04-27 13:32:52 +0200863 }
danilchap47a740b2015-12-15 00:30:07 -0800864 // The interval between RTCP packets is varied randomly over the
865 // range [1/2,3/2] times the calculated interval.
866 uint32_t timeToNext =
867 random_.Rand(minIntervalMs * 1 / 2, minIntervalMs * 3 / 2);
Erik Språng242e22b2015-05-11 10:17:43 +0200868 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000869
Per83d09102016-04-15 14:59:13 +0200870 if (receive_statistics_) {
871 StatisticianMap statisticians =
872 receive_statistics_->GetActiveStatisticians();
873 RTC_DCHECK(report_blocks_.empty());
874 for (auto& it : statisticians) {
875 AddReportBlock(feedback_state, it.first, it.second);
876 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000877 }
878 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000879}
880
danilchapa72e7342015-12-22 08:07:45 -0800881bool RTCPSender::AddReportBlock(const FeedbackState& feedback_state,
882 uint32_t ssrc,
883 StreamStatistician* statistician) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000884 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000885 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000886 if (!statistician->GetStatistics(&stats, true))
887 return false;
danilchapa72e7342015-12-22 08:07:45 -0800888
889 if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) {
890 LOG(LS_WARNING) << "Too many report blocks.";
891 return false;
892 }
893 RTC_DCHECK(report_blocks_.find(ssrc) == report_blocks_.end());
894 rtcp::ReportBlock* block = &report_blocks_[ssrc];
895 block->To(ssrc);
896 block->WithFractionLost(stats.fraction_lost);
897 if (!block->WithCumulativeLost(stats.cumulative_lost)) {
898 report_blocks_.erase(ssrc);
899 LOG(LS_WARNING) << "Cumulative lost is oversized.";
900 return false;
901 }
902 block->WithExtHighestSeqNum(stats.extended_max_sequence_number);
903 block->WithJitter(stats.jitter);
904 block->WithLastSr(feedback_state.remote_sr);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000905
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200906 // TODO(sprang): Do we really need separate time stamps for each report?
907 // Get our NTP as late as possible to avoid a race.
908 uint32_t ntp_secs;
909 uint32_t ntp_frac;
910 clock_->CurrentNtp(ntp_secs, ntp_frac);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000911
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200912 // Delay since last received report.
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000913 if ((feedback_state.last_rr_ntp_secs != 0) ||
914 (feedback_state.last_rr_ntp_frac != 0)) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200915 // Get the 16 lowest bits of seconds and the 16 highest bits of fractions.
916 uint32_t now = ntp_secs & 0x0000FFFF;
Erik Språng61be2a42015-04-27 13:32:52 +0200917 now <<= 16;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200918 now += (ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000919
Erik Språng61be2a42015-04-27 13:32:52 +0200920 uint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
921 receiveTime <<= 16;
922 receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000923
danilchapa72e7342015-12-22 08:07:45 -0800924 block->WithDelayLastSr(now - receiveTime);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000925 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000926 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000927}
928
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000929void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
danilchap56036ff2016-03-22 11:14:09 -0700930 RTC_DCHECK_LE(csrcs.size(), static_cast<size_t>(kRtpCsrcSize));
931 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000932 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +0000933}
934
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000935int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
936 uint32_t name,
937 const uint8_t* data,
938 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +0200939 if (length % 4 != 0) {
940 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
941 return -1;
942 }
danilchap56036ff2016-03-22 11:14:09 -0700943 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000944
Erik Språng242e22b2015-05-11 10:17:43 +0200945 SetFlag(kRtcpApp, true);
946 app_sub_type_ = subType;
947 app_name_ = name;
948 app_data_.reset(new uint8_t[length]);
949 app_length_ = length;
950 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +0200951 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000952}
953
Erik Språng61be2a42015-04-27 13:32:52 +0200954int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
danilchap56036ff2016-03-22 11:14:09 -0700955 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200956 memcpy(&xr_voip_metric_, VoIPMetric, sizeof(RTCPVoIPMetric));
niklase@google.com470e71d2011-07-07 08:21:25 +0000957
Erik Språng242e22b2015-05-11 10:17:43 +0200958 SetFlag(kRtcpXrVoipMetric, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200959 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000960}
961
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000962void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700963 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200964 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000965}
966
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000967bool RTCPSender::RtcpXrReceiverReferenceTime() const {
danilchap56036ff2016-03-22 11:14:09 -0700968 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200969 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000970}
971
niklase@google.com470e71d2011-07-07 08:21:25 +0000972// no callbacks allowed inside this function
danilchap6eaa3a42016-05-09 10:59:50 -0700973void RTCPSender::SetTMMBN(const std::vector<rtcp::TmmbItem>* bounding_set) {
danilchap56036ff2016-03-22 11:14:09 -0700974 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap6eaa3a42016-05-09 10:59:50 -0700975 if (bounding_set) {
976 tmmbn_to_send_ = *bounding_set;
977 } else {
978 tmmbn_to_send_.clear();
Erik Språng61be2a42015-04-27 13:32:52 +0200979 }
danilchap6eaa3a42016-05-09 10:59:50 -0700980 SetFlag(kRtcpTmmbn, true);
niklase@google.com470e71d2011-07-07 08:21:25 +0000981}
Erik Språng61be2a42015-04-27 13:32:52 +0200982
Erik Språng242e22b2015-05-11 10:17:43 +0200983void RTCPSender::SetFlag(RTCPPacketType type, bool is_volatile) {
984 report_flags_.insert(ReportFlag(type, is_volatile));
985}
986
987void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
988 bool is_volatile) {
989 for (RTCPPacketType type : types)
990 SetFlag(type, is_volatile);
991}
992
993bool RTCPSender::IsFlagPresent(RTCPPacketType type) const {
994 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
995}
996
997bool RTCPSender::ConsumeFlag(RTCPPacketType type, bool forced) {
998 auto it = report_flags_.find(ReportFlag(type, false));
999 if (it == report_flags_.end())
1000 return false;
1001 if (it->is_volatile || forced)
1002 report_flags_.erase((it));
1003 return true;
1004}
1005
1006bool RTCPSender::AllVolatileFlagsConsumed() const {
1007 for (const ReportFlag& flag : report_flags_) {
1008 if (flag.is_volatile)
1009 return false;
1010 }
1011 return true;
1012}
1013
sprang233bd872015-09-08 13:25:16 -07001014bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
sprang233bd872015-09-08 13:25:16 -07001015 class Sender : public rtcp::RtcpPacket::PacketReadyCallback {
1016 public:
terelius429c3452016-01-21 05:42:04 -08001017 Sender(Transport* transport, RtcEventLog* event_log)
1018 : transport_(transport), event_log_(event_log), send_failure_(false) {}
sprang233bd872015-09-08 13:25:16 -07001019
1020 void OnPacketReady(uint8_t* data, size_t length) override {
terelius429c3452016-01-21 05:42:04 -08001021 if (transport_->SendRtcp(data, length)) {
1022 if (event_log_) {
1023 event_log_->LogRtcpPacket(kOutgoingPacket, MediaType::ANY, data,
1024 length);
1025 }
1026 } else {
sprang233bd872015-09-08 13:25:16 -07001027 send_failure_ = true;
terelius429c3452016-01-21 05:42:04 -08001028 }
sprang233bd872015-09-08 13:25:16 -07001029 }
1030
1031 Transport* const transport_;
terelius429c3452016-01-21 05:42:04 -08001032 RtcEventLog* const event_log_;
sprang233bd872015-09-08 13:25:16 -07001033 bool send_failure_;
terelius429c3452016-01-21 05:42:04 -08001034 // TODO(terelius): We would like to
1035 // RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(Sender);
1036 // but we can't because of an incorrect warning (C4822) in MVS 2013.
1037 } sender(transport_, event_log_);
sprang233bd872015-09-08 13:25:16 -07001038
danilchap41befce2016-03-30 11:11:51 -07001039 RTC_DCHECK_LE(max_payload_length_, static_cast<size_t>(IP_PACKET_SIZE));
sprang233bd872015-09-08 13:25:16 -07001040 uint8_t buffer[IP_PACKET_SIZE];
danilchap41befce2016-03-30 11:11:51 -07001041 return packet.BuildExternalBuffer(buffer, max_payload_length_, &sender) &&
sprang233bd872015-09-08 13:25:16 -07001042 !sender.send_failure_;
1043}
1044
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001045} // namespace webrtc