blob: 7113807cf86ea0150931a3551caa687cbcc7c69b [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"
danilchap13deaad2016-05-24 13:25:27 -070039#include "webrtc/modules/rtp_rtcp/source/tmmbr_help.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000040
niklase@google.com470e71d2011-07-07 08:21:25 +000041namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000042
Erik Språng61be2a42015-04-27 13:32:52 +020043NACKStringBuilder::NACKStringBuilder()
danilchap162abd32015-12-10 02:39:40 -080044 : stream_(""), count_(0), prevNack_(0), consecutive_(false) {}
edjee@google.com79b02892013-04-04 19:43:34 +000045
pbos@webrtc.orgf3e4cee2013-07-31 15:17:19 +000046NACKStringBuilder::~NACKStringBuilder() {}
47
danilchap162abd32015-12-10 02:39:40 -080048void NACKStringBuilder::PushNACK(uint16_t nack) {
Erik Språng242e22b2015-05-11 10:17:43 +020049 if (count_ == 0) {
50 stream_ << nack;
51 } else if (nack == prevNack_ + 1) {
52 consecutive_ = true;
Erik Språng61be2a42015-04-27 13:32:52 +020053 } else {
Erik Språng242e22b2015-05-11 10:17:43 +020054 if (consecutive_) {
55 stream_ << "-" << prevNack_;
56 consecutive_ = false;
edjee@google.com79b02892013-04-04 19:43:34 +000057 }
Erik Språng242e22b2015-05-11 10:17:43 +020058 stream_ << "," << nack;
Erik Språng61be2a42015-04-27 13:32:52 +020059 }
Erik Språng242e22b2015-05-11 10:17:43 +020060 count_++;
61 prevNack_ = nack;
edjee@google.com79b02892013-04-04 19:43:34 +000062}
63
Erik Språng61be2a42015-04-27 13:32:52 +020064std::string NACKStringBuilder::GetResult() {
Erik Språng242e22b2015-05-11 10:17:43 +020065 if (consecutive_) {
66 stream_ << "-" << prevNack_;
67 consecutive_ = false;
Erik Språng61be2a42015-04-27 13:32:52 +020068 }
Erik Språng242e22b2015-05-11 10:17:43 +020069 return stream_.str();
edjee@google.com79b02892013-04-04 19:43:34 +000070}
71
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000072RTCPSender::FeedbackState::FeedbackState()
73 : send_payload_type(0),
74 frequency_hz(0),
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +000075 packets_sent(0),
76 media_bytes_sent(0),
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000077 send_bitrate(0),
78 last_rr_ntp_secs(0),
79 last_rr_ntp_frac(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000080 remote_sr(0),
Erik Språng61be2a42015-04-27 13:32:52 +020081 has_last_xr_rr(false),
danilchap162abd32015-12-10 02:39:40 -080082 module(nullptr) {}
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000083
danilchap2f7dea12016-01-13 02:03:04 -080084class PacketContainer : public rtcp::CompoundPacket,
Erik Språngf7c57762015-12-04 10:40:35 +010085 public rtcp::RtcpPacket::PacketReadyCallback {
86 public:
terelius429c3452016-01-21 05:42:04 -080087 PacketContainer(Transport* transport, RtcEventLog* event_log)
88 : transport_(transport), event_log_(event_log), bytes_sent_(0) {}
Erik Språngf7c57762015-12-04 10:40:35 +010089 virtual ~PacketContainer() {
90 for (RtcpPacket* packet : appended_packets_)
91 delete packet;
92 }
93
94 void OnPacketReady(uint8_t* data, size_t length) override {
terelius429c3452016-01-21 05:42:04 -080095 if (transport_->SendRtcp(data, length)) {
Erik Språngf7c57762015-12-04 10:40:35 +010096 bytes_sent_ += length;
terelius429c3452016-01-21 05:42:04 -080097 if (event_log_) {
98 event_log_->LogRtcpPacket(kOutgoingPacket, MediaType::ANY, data,
99 length);
100 }
101 }
Erik Språngf7c57762015-12-04 10:40:35 +0100102 }
103
danilchap41befce2016-03-30 11:11:51 -0700104 size_t SendPackets(size_t max_payload_length) {
105 RTC_DCHECK_LE(max_payload_length, static_cast<size_t>(IP_PACKET_SIZE));
106 uint8_t buffer[IP_PACKET_SIZE];
107 BuildExternalBuffer(buffer, max_payload_length, this);
Erik Språngf7c57762015-12-04 10:40:35 +0100108 return bytes_sent_;
109 }
110
111 private:
112 Transport* transport_;
terelius429c3452016-01-21 05:42:04 -0800113 RtcEventLog* const event_log_;
Erik Språngf7c57762015-12-04 10:40:35 +0100114 size_t bytes_sent_;
terelius429c3452016-01-21 05:42:04 -0800115
116 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(PacketContainer);
Erik Språngf7c57762015-12-04 10:40:35 +0100117};
118
119class RTCPSender::RtcpContext {
120 public:
Erik Språng242e22b2015-05-11 10:17:43 +0200121 RtcpContext(const FeedbackState& feedback_state,
122 int32_t nack_size,
123 const uint16_t* nack_list,
124 bool repeat,
125 uint64_t picture_id,
Erik Språngf7c57762015-12-04 10:40:35 +0100126 uint32_t ntp_sec,
danilchap56036ff2016-03-22 11:14:09 -0700127 uint32_t ntp_frac)
Erik Språngf7c57762015-12-04 10:40:35 +0100128 : feedback_state_(feedback_state),
129 nack_size_(nack_size),
130 nack_list_(nack_list),
131 repeat_(repeat),
132 picture_id_(picture_id),
133 ntp_sec_(ntp_sec),
danilchap56036ff2016-03-22 11:14:09 -0700134 ntp_frac_(ntp_frac) {}
Erik Språng242e22b2015-05-11 10:17:43 +0200135
Erik Språngf7c57762015-12-04 10:40:35 +0100136 const FeedbackState& feedback_state_;
137 const int32_t nack_size_;
138 const uint16_t* nack_list_;
139 const bool repeat_;
140 const uint64_t picture_id_;
141 const uint32_t ntp_sec_;
142 const uint32_t ntp_frac_;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200143};
144
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000145RTCPSender::RTCPSender(
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000146 bool audio,
147 Clock* clock,
148 ReceiveStatistics* receive_statistics,
sprang86fd9ed2015-09-29 04:45:43 -0700149 RtcpPacketTypeCounterObserver* packet_type_counter_observer,
terelius429c3452016-01-21 05:42:04 -0800150 RtcEventLog* event_log,
sprang86fd9ed2015-09-29 04:45:43 -0700151 Transport* outgoing_transport)
Peter Boströmac547a62015-09-17 23:03:57 +0200152 : audio_(audio),
Erik Språng242e22b2015-05-11 10:17:43 +0200153 clock_(clock),
danilchap47a740b2015-12-15 00:30:07 -0800154 random_(clock_->TimeInMicroseconds()),
pbosda903ea2015-10-02 02:36:56 -0700155 method_(RtcpMode::kOff),
terelius429c3452016-01-21 05:42:04 -0800156 event_log_(event_log),
sprang86fd9ed2015-09-29 04:45:43 -0700157 transport_(outgoing_transport),
Erik Språng242e22b2015-05-11 10:17:43 +0200158 using_nack_(false),
159 sending_(false),
160 remb_enabled_(false),
Erik Språng242e22b2015-05-11 10:17:43 +0200161 next_time_to_send_rtcp_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000162 start_timestamp_(0),
163 last_rtp_timestamp_(0),
164 last_frame_capture_time_ms_(-1),
Erik Språng242e22b2015-05-11 10:17:43 +0200165 ssrc_(0),
166 remote_ssrc_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000167 receive_statistics_(receive_statistics),
niklase@google.com470e71d2011-07-07 08:21:25 +0000168
Erik Språng242e22b2015-05-11 10:17:43 +0200169 sequence_number_fir_(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000170
Erik Språng242e22b2015-05-11 10:17:43 +0200171 remb_bitrate_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000172
Erik Språng242e22b2015-05-11 10:17:43 +0200173 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
danilchap13deaad2016-05-24 13:25:27 -0700588 TMMBRHelp tmmbr_help;
Erik Språng61be2a42015-04-27 13:32:52 +0200589 // get current bounding set from RTCP receiver
590 bool tmmbrOwner = false;
591 // store in candidateSet, allocates one extra slot
danilchap13deaad2016-05-24 13:25:27 -0700592 TMMBRSet* candidateSet = tmmbr_help.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000593
Erik Språng242e22b2015-05-11 10:17:43 +0200594 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
595 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
Erik Språng61be2a42015-04-27 13:32:52 +0200596 // since RTCPreceiver is not doing the reverse we should be fine
597 int32_t lengthOfBoundingSet =
danilchap6db6cdc2015-12-15 02:54:47 -0800598 ctx.feedback_state_.module->BoundingSet(&tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +0000599
Erik Språng61be2a42015-04-27 13:32:52 +0200600 if (lengthOfBoundingSet > 0) {
601 for (int32_t i = 0; i < lengthOfBoundingSet; i++) {
Erik Språng242e22b2015-05-11 10:17:43 +0200602 if (candidateSet->Tmmbr(i) == tmmbr_send_ &&
603 candidateSet->PacketOH(i) == packet_oh_send_) {
Erik Språngf7c57762015-12-04 10:40:35 +0100604 // Do not send the same tuple.
605 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200606 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000607 }
Erik Språng61be2a42015-04-27 13:32:52 +0200608 if (!tmmbrOwner) {
609 // use received bounding set as candidate set
610 // add current tuple
Erik Språng242e22b2015-05-11 10:17:43 +0200611 candidateSet->SetEntry(lengthOfBoundingSet, tmmbr_send_, packet_oh_send_,
612 ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200613 int numCandidates = lengthOfBoundingSet + 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000614
Erik Språng61be2a42015-04-27 13:32:52 +0200615 // find bounding set
Erik Språngf7c57762015-12-04 10:40:35 +0100616 TMMBRSet* boundingSet = nullptr;
danilchap13deaad2016-05-24 13:25:27 -0700617 int numBoundingSet = tmmbr_help.FindTMMBRBoundingSet(boundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200618 if (numBoundingSet > 0 || numBoundingSet <= numCandidates)
danilchap13deaad2016-05-24 13:25:27 -0700619 tmmbrOwner = tmmbr_help.IsOwner(ssrc_, numBoundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200620 if (!tmmbrOwner) {
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
Erik Språngf7c57762015-12-04 10:40:35 +0100627 if (!tmmbr_send_)
628 return nullptr;
sprang81a3e602015-08-21 05:30:11 -0700629
Erik Språngf7c57762015-12-04 10:40:35 +0100630 rtcp::Tmmbr* tmmbr = new rtcp::Tmmbr();
631 tmmbr->From(ssrc_);
danilchapf174e3a2016-02-05 04:56:36 -0800632 rtcp::TmmbItem request;
633 request.set_ssrc(remote_ssrc_);
634 request.set_bitrate_bps(tmmbr_send_ * 1000);
635 request.set_packet_overhead(packet_oh_send_);
636 tmmbr->WithTmmbr(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();
644 tmmbn->From(ssrc_);
danilchap6eaa3a42016-05-09 10:59:50 -0700645 for (const rtcp::TmmbItem& tmmbr : tmmbn_to_send_) {
646 if (tmmbr.bitrate_bps() > 0) {
647 tmmbn->WithTmmbr(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();
656 app->From(ssrc_);
657 app->WithSubType(app_sub_type_);
658 app->WithName(app_name_);
659 app->WithData(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();
667 nack->From(ssrc_);
668 nack->To(remote_ssrc_);
669 nack->WithList(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();
692 bye->From(ssrc_);
sprangd8ee4f92015-08-24 03:25:19 -0700693 for (uint32_t csrc : csrcs_)
Erik Språngf7c57762015-12-04 10:40:35 +0100694 bye->WithCsrc(csrc);
sprangd8ee4f92015-08-24 03:25:19 -0700695
danilchap56036ff2016-03-22 11:14:09 -0700696 return std::unique_ptr<rtcp::RtcpPacket>(bye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000697}
698
danilchap56036ff2016-03-22 11:14:09 -0700699std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildReceiverReferenceTime(
Erik Språngf7c57762015-12-04 10:40:35 +0100700 const RtcpContext& ctx) {
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000701
Danil Chapovalov256e5b22016-01-15 14:16:24 +0100702 rtcp::ExtendedReports* xr = new rtcp::ExtendedReports();
Erik Språngf7c57762015-12-04 10:40:35 +0100703 xr->From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000704
Erik Språngca28fdc2015-08-31 14:00:50 +0200705 rtcp::Rrtr rrtr;
Danil Chapovalovfc47ed62015-12-07 14:46:35 +0100706 rrtr.WithNtp(NtpTime(ctx.ntp_sec_, ctx.ntp_frac_));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000707
danilchapde138822016-01-29 11:26:14 -0800708 xr->WithRrtr(rrtr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000709
Erik Språngca28fdc2015-08-31 14:00:50 +0200710 // TODO(sprang): Merge XR report sending to contain all of RRTR, DLRR, VOIP?
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000711
danilchap56036ff2016-03-22 11:14:09 -0700712 return std::unique_ptr<rtcp::RtcpPacket>(xr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000713}
714
danilchap56036ff2016-03-22 11:14:09 -0700715std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildDlrr(
Erik Språngf7c57762015-12-04 10:40:35 +0100716 const RtcpContext& ctx) {
Danil Chapovalov256e5b22016-01-15 14:16:24 +0100717 rtcp::ExtendedReports* xr = new rtcp::ExtendedReports();
Erik Språngf7c57762015-12-04 10:40:35 +0100718 xr->From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000719
Erik Språngca28fdc2015-08-31 14:00:50 +0200720 rtcp::Dlrr dlrr;
Erik Språngf7c57762015-12-04 10:40:35 +0100721 const RtcpReceiveTimeInfo& info = ctx.feedback_state_.last_xr_rr;
Erik Språngca28fdc2015-08-31 14:00:50 +0200722 dlrr.WithDlrrItem(info.sourceSSRC, info.lastRR, info.delaySinceLastRR);
723
danilchapde138822016-01-29 11:26:14 -0800724 xr->WithDlrr(dlrr);
Erik Språngca28fdc2015-08-31 14:00:50 +0200725
danilchap56036ff2016-03-22 11:14:09 -0700726 return std::unique_ptr<rtcp::RtcpPacket>(xr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000727}
728
Erik Språng242e22b2015-05-11 10:17:43 +0200729// TODO(sprang): Add a unit test for this, or remove if the code isn't used.
danilchap56036ff2016-03-22 11:14:09 -0700730std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildVoIPMetric(
Erik Språngf7c57762015-12-04 10:40:35 +0100731 const RtcpContext& context) {
Danil Chapovalov256e5b22016-01-15 14:16:24 +0100732 rtcp::ExtendedReports* xr = new rtcp::ExtendedReports();
Erik Språngf7c57762015-12-04 10:40:35 +0100733 xr->From(ssrc_);
Erik Språngca28fdc2015-08-31 14:00:50 +0200734
735 rtcp::VoipMetric voip;
736 voip.To(remote_ssrc_);
danilchap91941ae2015-12-15 07:06:36 -0800737 voip.WithVoipMetric(xr_voip_metric_);
Erik Språngca28fdc2015-08-31 14:00:50 +0200738
danilchapde138822016-01-29 11:26:14 -0800739 xr->WithVoipMetric(voip);
Erik Språngca28fdc2015-08-31 14:00:50 +0200740
danilchap56036ff2016-03-22 11:14:09 -0700741 return std::unique_ptr<rtcp::RtcpPacket>(xr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000742}
743
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000744int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200745 RTCPPacketType packetType,
746 int32_t nack_size,
747 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000748 bool repeat,
749 uint64_t pictureID) {
Erik Språng242e22b2015-05-11 10:17:43 +0200750 return SendCompoundRTCP(
751 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
752 nack_size, nack_list, repeat, pictureID);
753}
754
755int32_t RTCPSender::SendCompoundRTCP(
756 const FeedbackState& feedback_state,
Erik Språngf7c57762015-12-04 10:40:35 +0100757 const std::set<RTCPPacketType>& packet_types,
Erik Språng242e22b2015-05-11 10:17:43 +0200758 int32_t nack_size,
759 const uint16_t* nack_list,
760 bool repeat,
761 uint64_t pictureID) {
terelius429c3452016-01-21 05:42:04 -0800762 PacketContainer container(transport_, event_log_);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000763 {
danilchap56036ff2016-03-22 11:14:09 -0700764 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbosda903ea2015-10-02 02:36:56 -0700765 if (method_ == RtcpMode::kOff) {
Erik Språng61be2a42015-04-27 13:32:52 +0200766 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
767 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +0000768 }
Erik Språngf7c57762015-12-04 10:40:35 +0100769
770 // We need to send our NTP even if we haven't received any reports.
771 uint32_t ntp_sec;
772 uint32_t ntp_frac;
773 clock_->CurrentNtp(ntp_sec, ntp_frac);
774 RtcpContext context(feedback_state, nack_size, nack_list, repeat, pictureID,
danilchap56036ff2016-03-22 11:14:09 -0700775 ntp_sec, ntp_frac);
Erik Språngf7c57762015-12-04 10:40:35 +0100776
777 PrepareReport(packet_types, feedback_state);
778
danilchap56036ff2016-03-22 11:14:09 -0700779 std::unique_ptr<rtcp::RtcpPacket> packet_bye;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800780
Erik Språngf7c57762015-12-04 10:40:35 +0100781 auto it = report_flags_.begin();
782 while (it != report_flags_.end()) {
783 auto builder_it = builders_.find(it->type);
784 RTC_DCHECK(builder_it != builders_.end());
785 if (it->is_volatile) {
786 report_flags_.erase(it++);
787 } else {
788 ++it;
789 }
790
791 BuilderFunc func = builder_it->second;
danilchap56036ff2016-03-22 11:14:09 -0700792 std::unique_ptr<rtcp::RtcpPacket> packet = (this->*func)(context);
Erik Språngf7c57762015-12-04 10:40:35 +0100793 if (packet.get() == nullptr)
794 return -1;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800795 // If there is a BYE, don't append now - save it and append it
796 // at the end later.
797 if (builder_it->first == kRtcpBye) {
798 packet_bye = std::move(packet);
799 } else {
800 container.Append(packet.release());
801 }
802 }
803
804 // Append the BYE now at the end
805 if (packet_bye) {
806 container.Append(packet_bye.release());
Erik Språngf7c57762015-12-04 10:40:35 +0100807 }
808
809 if (packet_type_counter_observer_ != nullptr) {
810 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
811 remote_ssrc_, packet_type_counter_);
812 }
813
814 RTC_DCHECK(AllVolatileFlagsConsumed());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000815 }
Erik Språng61be2a42015-04-27 13:32:52 +0200816
danilchap41befce2016-03-30 11:11:51 -0700817 size_t bytes_sent = container.SendPackets(max_payload_length_);
Erik Språngf7c57762015-12-04 10:40:35 +0100818 return bytes_sent == 0 ? -1 : 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000819}
820
Erik Språngf7c57762015-12-04 10:40:35 +0100821void RTCPSender::PrepareReport(const std::set<RTCPPacketType>& packetTypes,
822 const FeedbackState& feedback_state) {
Erik Språng242e22b2015-05-11 10:17:43 +0200823 // Add all flags as volatile. Non volatile entries will not be overwritten
824 // and all new volatile flags added will be consumed by the end of this call.
825 SetFlags(packetTypes, true);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000826
Erik Språng61be2a42015-04-27 13:32:52 +0200827 if (packet_type_counter_.first_packet_time_ms == -1)
Erik Språng242e22b2015-05-11 10:17:43 +0200828 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språng61be2a42015-04-27 13:32:52 +0200829
Erik Språng242e22b2015-05-11 10:17:43 +0200830 bool generate_report;
831 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
832 // Report type already explicitly set, don't automatically populate.
833 generate_report = true;
henrikg91d6ede2015-09-17 00:24:34 -0700834 RTC_DCHECK(ConsumeFlag(kRtcpReport) == false);
Erik Språng242e22b2015-05-11 10:17:43 +0200835 } else {
836 generate_report =
pbosda903ea2015-10-02 02:36:56 -0700837 (ConsumeFlag(kRtcpReport) && method_ == RtcpMode::kReducedSize) ||
838 method_ == RtcpMode::kCompound;
Erik Språng242e22b2015-05-11 10:17:43 +0200839 if (generate_report)
840 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000841 }
842
Erik Språng0ea42d32015-06-25 14:46:16 +0200843 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
Erik Språng242e22b2015-05-11 10:17:43 +0200844 SetFlag(kRtcpSdes, true);
845
Erik Språng242e22b2015-05-11 10:17:43 +0200846 if (generate_report) {
847 if (!sending_ && xr_send_receiver_reference_time_enabled_)
848 SetFlag(kRtcpXrReceiverReferenceTime, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200849 if (feedback_state.has_last_xr_rr)
Erik Språng242e22b2015-05-11 10:17:43 +0200850 SetFlag(kRtcpXrDlrrReportBlock, true);
851
852 // generate next time to send an RTCP report
danilchap47a740b2015-12-15 00:30:07 -0800853 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000854
danilchap47a740b2015-12-15 00:30:07 -0800855 if (!audio_) {
Erik Språng242e22b2015-05-11 10:17:43 +0200856 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200857 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
858 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
859 if (send_bitrate_kbit != 0)
860 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000861 }
Erik Språng61be2a42015-04-27 13:32:52 +0200862 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
863 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
Erik Språng61be2a42015-04-27 13:32:52 +0200864 }
danilchap47a740b2015-12-15 00:30:07 -0800865 // The interval between RTCP packets is varied randomly over the
866 // range [1/2,3/2] times the calculated interval.
867 uint32_t timeToNext =
868 random_.Rand(minIntervalMs * 1 / 2, minIntervalMs * 3 / 2);
Erik Språng242e22b2015-05-11 10:17:43 +0200869 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000870
Per83d09102016-04-15 14:59:13 +0200871 if (receive_statistics_) {
872 StatisticianMap statisticians =
873 receive_statistics_->GetActiveStatisticians();
874 RTC_DCHECK(report_blocks_.empty());
875 for (auto& it : statisticians) {
876 AddReportBlock(feedback_state, it.first, it.second);
877 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000878 }
879 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000880}
881
danilchapa72e7342015-12-22 08:07:45 -0800882bool RTCPSender::AddReportBlock(const FeedbackState& feedback_state,
883 uint32_t ssrc,
884 StreamStatistician* statistician) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000885 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000886 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000887 if (!statistician->GetStatistics(&stats, true))
888 return false;
danilchapa72e7342015-12-22 08:07:45 -0800889
890 if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) {
891 LOG(LS_WARNING) << "Too many report blocks.";
892 return false;
893 }
894 RTC_DCHECK(report_blocks_.find(ssrc) == report_blocks_.end());
895 rtcp::ReportBlock* block = &report_blocks_[ssrc];
896 block->To(ssrc);
897 block->WithFractionLost(stats.fraction_lost);
898 if (!block->WithCumulativeLost(stats.cumulative_lost)) {
899 report_blocks_.erase(ssrc);
900 LOG(LS_WARNING) << "Cumulative lost is oversized.";
901 return false;
902 }
903 block->WithExtHighestSeqNum(stats.extended_max_sequence_number);
904 block->WithJitter(stats.jitter);
905 block->WithLastSr(feedback_state.remote_sr);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000906
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200907 // TODO(sprang): Do we really need separate time stamps for each report?
908 // Get our NTP as late as possible to avoid a race.
909 uint32_t ntp_secs;
910 uint32_t ntp_frac;
911 clock_->CurrentNtp(ntp_secs, ntp_frac);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000912
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200913 // Delay since last received report.
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000914 if ((feedback_state.last_rr_ntp_secs != 0) ||
915 (feedback_state.last_rr_ntp_frac != 0)) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200916 // Get the 16 lowest bits of seconds and the 16 highest bits of fractions.
917 uint32_t now = ntp_secs & 0x0000FFFF;
Erik Språng61be2a42015-04-27 13:32:52 +0200918 now <<= 16;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200919 now += (ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000920
Erik Språng61be2a42015-04-27 13:32:52 +0200921 uint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
922 receiveTime <<= 16;
923 receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000924
danilchapa72e7342015-12-22 08:07:45 -0800925 block->WithDelayLastSr(now - receiveTime);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000926 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000927 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000928}
929
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000930void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
danilchap56036ff2016-03-22 11:14:09 -0700931 RTC_DCHECK_LE(csrcs.size(), static_cast<size_t>(kRtpCsrcSize));
932 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000933 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +0000934}
935
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000936int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
937 uint32_t name,
938 const uint8_t* data,
939 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +0200940 if (length % 4 != 0) {
941 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
942 return -1;
943 }
danilchap56036ff2016-03-22 11:14:09 -0700944 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000945
Erik Språng242e22b2015-05-11 10:17:43 +0200946 SetFlag(kRtcpApp, true);
947 app_sub_type_ = subType;
948 app_name_ = name;
949 app_data_.reset(new uint8_t[length]);
950 app_length_ = length;
951 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +0200952 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000953}
954
Erik Språng61be2a42015-04-27 13:32:52 +0200955int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
danilchap56036ff2016-03-22 11:14:09 -0700956 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200957 memcpy(&xr_voip_metric_, VoIPMetric, sizeof(RTCPVoIPMetric));
niklase@google.com470e71d2011-07-07 08:21:25 +0000958
Erik Språng242e22b2015-05-11 10:17:43 +0200959 SetFlag(kRtcpXrVoipMetric, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200960 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000961}
962
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000963void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700964 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200965 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000966}
967
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000968bool RTCPSender::RtcpXrReceiverReferenceTime() const {
danilchap56036ff2016-03-22 11:14:09 -0700969 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200970 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000971}
972
niklase@google.com470e71d2011-07-07 08:21:25 +0000973// no callbacks allowed inside this function
danilchap6eaa3a42016-05-09 10:59:50 -0700974void RTCPSender::SetTMMBN(const std::vector<rtcp::TmmbItem>* bounding_set) {
danilchap56036ff2016-03-22 11:14:09 -0700975 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap6eaa3a42016-05-09 10:59:50 -0700976 if (bounding_set) {
977 tmmbn_to_send_ = *bounding_set;
978 } else {
979 tmmbn_to_send_.clear();
Erik Språng61be2a42015-04-27 13:32:52 +0200980 }
danilchap6eaa3a42016-05-09 10:59:50 -0700981 SetFlag(kRtcpTmmbn, true);
niklase@google.com470e71d2011-07-07 08:21:25 +0000982}
Erik Språng61be2a42015-04-27 13:32:52 +0200983
Erik Språng242e22b2015-05-11 10:17:43 +0200984void RTCPSender::SetFlag(RTCPPacketType type, bool is_volatile) {
985 report_flags_.insert(ReportFlag(type, is_volatile));
986}
987
988void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
989 bool is_volatile) {
990 for (RTCPPacketType type : types)
991 SetFlag(type, is_volatile);
992}
993
994bool RTCPSender::IsFlagPresent(RTCPPacketType type) const {
995 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
996}
997
998bool RTCPSender::ConsumeFlag(RTCPPacketType type, bool forced) {
999 auto it = report_flags_.find(ReportFlag(type, false));
1000 if (it == report_flags_.end())
1001 return false;
1002 if (it->is_volatile || forced)
1003 report_flags_.erase((it));
1004 return true;
1005}
1006
1007bool RTCPSender::AllVolatileFlagsConsumed() const {
1008 for (const ReportFlag& flag : report_flags_) {
1009 if (flag.is_volatile)
1010 return false;
1011 }
1012 return true;
1013}
1014
sprang233bd872015-09-08 13:25:16 -07001015bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
sprang233bd872015-09-08 13:25:16 -07001016 class Sender : public rtcp::RtcpPacket::PacketReadyCallback {
1017 public:
terelius429c3452016-01-21 05:42:04 -08001018 Sender(Transport* transport, RtcEventLog* event_log)
1019 : transport_(transport), event_log_(event_log), send_failure_(false) {}
sprang233bd872015-09-08 13:25:16 -07001020
1021 void OnPacketReady(uint8_t* data, size_t length) override {
terelius429c3452016-01-21 05:42:04 -08001022 if (transport_->SendRtcp(data, length)) {
1023 if (event_log_) {
1024 event_log_->LogRtcpPacket(kOutgoingPacket, MediaType::ANY, data,
1025 length);
1026 }
1027 } else {
sprang233bd872015-09-08 13:25:16 -07001028 send_failure_ = true;
terelius429c3452016-01-21 05:42:04 -08001029 }
sprang233bd872015-09-08 13:25:16 -07001030 }
1031
1032 Transport* const transport_;
terelius429c3452016-01-21 05:42:04 -08001033 RtcEventLog* const event_log_;
sprang233bd872015-09-08 13:25:16 -07001034 bool send_failure_;
terelius429c3452016-01-21 05:42:04 -08001035 // TODO(terelius): We would like to
1036 // RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(Sender);
1037 // but we can't because of an incorrect warning (C4822) in MVS 2013.
1038 } sender(transport_, event_log_);
sprang233bd872015-09-08 13:25:16 -07001039
danilchap41befce2016-03-30 11:11:51 -07001040 RTC_DCHECK_LE(max_payload_length_, static_cast<size_t>(IP_PACKET_SIZE));
sprang233bd872015-09-08 13:25:16 -07001041 uint8_t buffer[IP_PACKET_SIZE];
danilchap41befce2016-03-30 11:11:51 -07001042 return packet.BuildExternalBuffer(buffer, max_payload_length_, &sender) &&
sprang233bd872015-09-08 13:25:16 -07001043 !sender.send_failure_;
1044}
1045
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001046} // namespace webrtc