blob: 8ef4f619ff03959d21c81ce58967e474fc022e8c [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
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000013#include <assert.h> // assert
stefan@webrtc.org9354cc92012-06-07 08:10:14 +000014#include <string.h> // memcpy
niklase@google.com470e71d2011-07-07 08:21:25 +000015
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000016#include <algorithm> // min
Erik Språng61be2a42015-04-27 13:32:52 +020017#include <limits> // max
danilchapb8b6fbb2015-12-10 05:05:27 -080018#include <utility>
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000019
Erik Språng61be2a42015-04-27 13:32:52 +020020#include "webrtc/base/checks.h"
Peter Boströmebc0b4e2015-10-28 16:39:33 +010021#include "webrtc/base/logging.h"
tommie4f96502015-10-20 23:00:48 -070022#include "webrtc/base/trace_event.h"
terelius429c3452016-01-21 05:42:04 -080023#include "webrtc/call.h"
24#include "webrtc/call/rtc_event_log.h"
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000025#include "webrtc/common_types.h"
sprang@webrtc.org779c3d12015-03-17 16:42:49 +000026#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
danilchap0219c9b2015-11-18 05:56:53 -080027#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/app.h"
danilchap50c51362015-11-22 09:03:11 -080028#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/bye.h"
danilchap2f7dea12016-01-13 02:03:04 -080029#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/compound_packet.h"
Danil Chapovalov256e5b22016-01-15 14:16:24 +010030#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_reports.h"
Danil Chapovalov5679da12016-01-15 13:19:53 +010031#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/fir.h"
danilchapa8890a52015-12-22 03:43:04 -080032#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/nack.h"
danilchapf8385ad2015-11-27 05:36:09 -080033#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/pli.h"
Danil Chapovalov97f7e132015-12-04 16:13:30 +010034#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
Danil Chapovalova5eba6c2016-01-15 12:40:15 +010035#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/remb.h"
Danil Chapovalov2c132972016-01-15 15:21:21 +010036#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rpsi.h"
Danil Chapovalov1567d0b2016-01-15 17:34:27 +010037#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sdes.h"
danilchap34ed2b92016-01-18 02:43:32 -080038#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sender_report.h"
danilchap92e677a2016-01-12 10:04:52 -080039#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sli.h"
danilchapef3d8052016-01-11 03:31:08 -080040#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbn.h"
danilchap7e8145f2016-01-11 11:49:19 -080041#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbr.h"
sprang233bd872015-09-08 13:25:16 -070042#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
tommie4f96502015-10-20 23:00:48 -070043#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010044#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000045
niklase@google.com470e71d2011-07-07 08:21:25 +000046namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000047
48using RTCPUtility::RTCPCnameInformation;
49
Erik Språng61be2a42015-04-27 13:32:52 +020050NACKStringBuilder::NACKStringBuilder()
danilchap162abd32015-12-10 02:39:40 -080051 : stream_(""), count_(0), prevNack_(0), consecutive_(false) {}
edjee@google.com79b02892013-04-04 19:43:34 +000052
pbos@webrtc.orgf3e4cee2013-07-31 15:17:19 +000053NACKStringBuilder::~NACKStringBuilder() {}
54
danilchap162abd32015-12-10 02:39:40 -080055void NACKStringBuilder::PushNACK(uint16_t nack) {
Erik Språng242e22b2015-05-11 10:17:43 +020056 if (count_ == 0) {
57 stream_ << nack;
58 } else if (nack == prevNack_ + 1) {
59 consecutive_ = true;
Erik Språng61be2a42015-04-27 13:32:52 +020060 } else {
Erik Språng242e22b2015-05-11 10:17:43 +020061 if (consecutive_) {
62 stream_ << "-" << prevNack_;
63 consecutive_ = false;
edjee@google.com79b02892013-04-04 19:43:34 +000064 }
Erik Språng242e22b2015-05-11 10:17:43 +020065 stream_ << "," << nack;
Erik Språng61be2a42015-04-27 13:32:52 +020066 }
Erik Språng242e22b2015-05-11 10:17:43 +020067 count_++;
68 prevNack_ = nack;
edjee@google.com79b02892013-04-04 19:43:34 +000069}
70
Erik Språng61be2a42015-04-27 13:32:52 +020071std::string NACKStringBuilder::GetResult() {
Erik Språng242e22b2015-05-11 10:17:43 +020072 if (consecutive_) {
73 stream_ << "-" << prevNack_;
74 consecutive_ = false;
Erik Språng61be2a42015-04-27 13:32:52 +020075 }
Erik Språng242e22b2015-05-11 10:17:43 +020076 return stream_.str();
edjee@google.com79b02892013-04-04 19:43:34 +000077}
78
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000079RTCPSender::FeedbackState::FeedbackState()
80 : send_payload_type(0),
81 frequency_hz(0),
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +000082 packets_sent(0),
83 media_bytes_sent(0),
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000084 send_bitrate(0),
85 last_rr_ntp_secs(0),
86 last_rr_ntp_frac(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000087 remote_sr(0),
Erik Språng61be2a42015-04-27 13:32:52 +020088 has_last_xr_rr(false),
danilchap162abd32015-12-10 02:39:40 -080089 module(nullptr) {}
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000090
danilchap2f7dea12016-01-13 02:03:04 -080091class PacketContainer : public rtcp::CompoundPacket,
Erik Språngf7c57762015-12-04 10:40:35 +010092 public rtcp::RtcpPacket::PacketReadyCallback {
93 public:
terelius429c3452016-01-21 05:42:04 -080094 PacketContainer(Transport* transport, RtcEventLog* event_log)
95 : transport_(transport), event_log_(event_log), bytes_sent_(0) {}
Erik Språngf7c57762015-12-04 10:40:35 +010096 virtual ~PacketContainer() {
97 for (RtcpPacket* packet : appended_packets_)
98 delete packet;
99 }
100
101 void OnPacketReady(uint8_t* data, size_t length) override {
terelius429c3452016-01-21 05:42:04 -0800102 if (transport_->SendRtcp(data, length)) {
Erik Språngf7c57762015-12-04 10:40:35 +0100103 bytes_sent_ += length;
terelius429c3452016-01-21 05:42:04 -0800104 if (event_log_) {
105 event_log_->LogRtcpPacket(kOutgoingPacket, MediaType::ANY, data,
106 length);
107 }
108 }
Erik Språngf7c57762015-12-04 10:40:35 +0100109 }
110
111 size_t SendPackets() {
danilchap2f7dea12016-01-13 02:03:04 -0800112 rtcp::CompoundPacket::Build(this);
Erik Språngf7c57762015-12-04 10:40:35 +0100113 return bytes_sent_;
114 }
115
116 private:
117 Transport* transport_;
terelius429c3452016-01-21 05:42:04 -0800118 RtcEventLog* const event_log_;
Erik Språngf7c57762015-12-04 10:40:35 +0100119 size_t bytes_sent_;
terelius429c3452016-01-21 05:42:04 -0800120
121 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(PacketContainer);
Erik Språngf7c57762015-12-04 10:40:35 +0100122};
123
124class RTCPSender::RtcpContext {
125 public:
Erik Språng242e22b2015-05-11 10:17:43 +0200126 RtcpContext(const FeedbackState& feedback_state,
127 int32_t nack_size,
128 const uint16_t* nack_list,
129 bool repeat,
130 uint64_t picture_id,
Erik Språngf7c57762015-12-04 10:40:35 +0100131 uint32_t ntp_sec,
132 uint32_t ntp_frac,
133 PacketContainer* container)
134 : feedback_state_(feedback_state),
135 nack_size_(nack_size),
136 nack_list_(nack_list),
137 repeat_(repeat),
138 picture_id_(picture_id),
139 ntp_sec_(ntp_sec),
140 ntp_frac_(ntp_frac),
141 container_(container) {}
Erik Språng242e22b2015-05-11 10:17:43 +0200142
Erik Språngf7c57762015-12-04 10:40:35 +0100143 virtual ~RtcpContext() {}
Erik Språng242e22b2015-05-11 10:17:43 +0200144
Erik Språngf7c57762015-12-04 10:40:35 +0100145 const FeedbackState& feedback_state_;
146 const int32_t nack_size_;
147 const uint16_t* nack_list_;
148 const bool repeat_;
149 const uint64_t picture_id_;
150 const uint32_t ntp_sec_;
151 const uint32_t ntp_frac_;
Erik Språng242e22b2015-05-11 10:17:43 +0200152
Erik Språngf7c57762015-12-04 10:40:35 +0100153 PacketContainer* const container_;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200154};
155
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000156RTCPSender::RTCPSender(
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000157 bool audio,
158 Clock* clock,
159 ReceiveStatistics* receive_statistics,
sprang86fd9ed2015-09-29 04:45:43 -0700160 RtcpPacketTypeCounterObserver* packet_type_counter_observer,
terelius429c3452016-01-21 05:42:04 -0800161 RtcEventLog* event_log,
sprang86fd9ed2015-09-29 04:45:43 -0700162 Transport* outgoing_transport)
Peter Boströmac547a62015-09-17 23:03:57 +0200163 : audio_(audio),
Erik Språng242e22b2015-05-11 10:17:43 +0200164 clock_(clock),
danilchap47a740b2015-12-15 00:30:07 -0800165 random_(clock_->TimeInMicroseconds()),
pbosda903ea2015-10-02 02:36:56 -0700166 method_(RtcpMode::kOff),
terelius429c3452016-01-21 05:42:04 -0800167 event_log_(event_log),
sprang86fd9ed2015-09-29 04:45:43 -0700168 transport_(outgoing_transport),
niklase@google.com470e71d2011-07-07 08:21:25 +0000169
Erik Språng242e22b2015-05-11 10:17:43 +0200170 critical_section_rtcp_sender_(
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000171 CriticalSectionWrapper::CreateCriticalSection()),
Erik Språng242e22b2015-05-11 10:17:43 +0200172 using_nack_(false),
173 sending_(false),
174 remb_enabled_(false),
Erik Språng242e22b2015-05-11 10:17:43 +0200175 next_time_to_send_rtcp_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000176 start_timestamp_(0),
177 last_rtp_timestamp_(0),
178 last_frame_capture_time_ms_(-1),
Erik Språng242e22b2015-05-11 10:17:43 +0200179 ssrc_(0),
180 remote_ssrc_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000181 receive_statistics_(receive_statistics),
niklase@google.com470e71d2011-07-07 08:21:25 +0000182
Erik Språng242e22b2015-05-11 10:17:43 +0200183 sequence_number_fir_(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000184
Erik Språng242e22b2015-05-11 10:17:43 +0200185 remb_bitrate_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000186
Erik Språng242e22b2015-05-11 10:17:43 +0200187 tmmbr_help_(),
188 tmmbr_send_(0),
189 packet_oh_send_(0),
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000190
Erik Språng242e22b2015-05-11 10:17:43 +0200191 app_sub_type_(0),
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200192 app_name_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200193 app_data_(nullptr),
194 app_length_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000195
Erik Språng242e22b2015-05-11 10:17:43 +0200196 xr_send_receiver_reference_time_enabled_(false),
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000197 packet_type_counter_observer_(packet_type_counter_observer) {
Erik Språng242e22b2015-05-11 10:17:43 +0200198 memset(last_send_report_, 0, sizeof(last_send_report_));
199 memset(last_rtcp_time_, 0, sizeof(last_rtcp_time_));
sprang86fd9ed2015-09-29 04:45:43 -0700200 RTC_DCHECK(transport_ != nullptr);
Erik Språng242e22b2015-05-11 10:17:43 +0200201
202 builders_[kRtcpSr] = &RTCPSender::BuildSR;
203 builders_[kRtcpRr] = &RTCPSender::BuildRR;
Erik Språng0ea42d32015-06-25 14:46:16 +0200204 builders_[kRtcpSdes] = &RTCPSender::BuildSDES;
Erik Språng242e22b2015-05-11 10:17:43 +0200205 builders_[kRtcpPli] = &RTCPSender::BuildPLI;
206 builders_[kRtcpFir] = &RTCPSender::BuildFIR;
207 builders_[kRtcpSli] = &RTCPSender::BuildSLI;
208 builders_[kRtcpRpsi] = &RTCPSender::BuildRPSI;
209 builders_[kRtcpRemb] = &RTCPSender::BuildREMB;
210 builders_[kRtcpBye] = &RTCPSender::BuildBYE;
211 builders_[kRtcpApp] = &RTCPSender::BuildAPP;
212 builders_[kRtcpTmmbr] = &RTCPSender::BuildTMMBR;
213 builders_[kRtcpTmmbn] = &RTCPSender::BuildTMMBN;
214 builders_[kRtcpNack] = &RTCPSender::BuildNACK;
215 builders_[kRtcpXrVoipMetric] = &RTCPSender::BuildVoIPMetric;
216 builders_[kRtcpXrReceiverReferenceTime] =
217 &RTCPSender::BuildReceiverReferenceTime;
218 builders_[kRtcpXrDlrrReportBlock] = &RTCPSender::BuildDlrr;
niklase@google.com470e71d2011-07-07 08:21:25 +0000219}
220
danilchap162abd32015-12-10 02:39:40 -0800221RTCPSender::~RTCPSender() {}
niklase@google.com470e71d2011-07-07 08:21:25 +0000222
pbosda903ea2015-10-02 02:36:56 -0700223RtcpMode RTCPSender::Status() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200224 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
225 return method_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000226}
227
pbosda903ea2015-10-02 02:36:56 -0700228void RTCPSender::SetRTCPStatus(RtcpMode method) {
Erik Språng242e22b2015-05-11 10:17:43 +0200229 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
230 method_ = method;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000231
pbosda903ea2015-10-02 02:36:56 -0700232 if (method == RtcpMode::kOff)
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000233 return;
Erik Språng242e22b2015-05-11 10:17:43 +0200234 next_time_to_send_rtcp_ =
235 clock_->TimeInMilliseconds() +
236 (audio_ ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000237}
238
Erik Språng61be2a42015-04-27 13:32:52 +0200239bool RTCPSender::Sending() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200240 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
241 return sending_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000242}
243
Erik Språng61be2a42015-04-27 13:32:52 +0200244int32_t RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
245 bool sending) {
246 bool sendRTCPBye = false;
247 {
Erik Språng242e22b2015-05-11 10:17:43 +0200248 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000249
pbosda903ea2015-10-02 02:36:56 -0700250 if (method_ != RtcpMode::kOff) {
Erik Språng242e22b2015-05-11 10:17:43 +0200251 if (sending == false && sending_ == true) {
Erik Språng61be2a42015-04-27 13:32:52 +0200252 // Trigger RTCP bye
253 sendRTCPBye = true;
254 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000255 }
Erik Språng242e22b2015-05-11 10:17:43 +0200256 sending_ = sending;
Erik Språng61be2a42015-04-27 13:32:52 +0200257 }
258 if (sendRTCPBye)
259 return SendRTCP(feedback_state, kRtcpBye);
260 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000261}
262
Erik Språng61be2a42015-04-27 13:32:52 +0200263bool RTCPSender::REMB() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200264 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
265 return remb_enabled_;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000266}
267
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000268void RTCPSender::SetREMBStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200269 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
270 remb_enabled_ = enable;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000271}
272
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000273void RTCPSender::SetREMBData(uint32_t bitrate,
274 const std::vector<uint32_t>& ssrcs) {
Erik Språng242e22b2015-05-11 10:17:43 +0200275 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
276 remb_bitrate_ = bitrate;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000277 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000278
Erik Språng242e22b2015-05-11 10:17:43 +0200279 if (remb_enabled_)
280 SetFlag(kRtcpRemb, false);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000281 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
282 // throttled by the caller.
Erik Språng242e22b2015-05-11 10:17:43 +0200283 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000284}
285
Erik Språng61be2a42015-04-27 13:32:52 +0200286bool RTCPSender::TMMBR() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200287 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
288 return IsFlagPresent(RTCPPacketType::kRtcpTmmbr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000289}
290
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000291void RTCPSender::SetTMMBRStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200292 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
293 if (enable) {
294 SetFlag(RTCPPacketType::kRtcpTmmbr, false);
295 } else {
296 ConsumeFlag(RTCPPacketType::kRtcpTmmbr, true);
297 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000298}
299
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000300void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
Erik Språng242e22b2015-05-11 10:17:43 +0200301 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000302 start_timestamp_ = start_timestamp;
303}
304
305void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
306 int64_t capture_time_ms) {
Erik Språng242e22b2015-05-11 10:17:43 +0200307 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000308 last_rtp_timestamp_ = rtp_timestamp;
309 if (capture_time_ms < 0) {
310 // We don't currently get a capture time from VoiceEngine.
Erik Språng242e22b2015-05-11 10:17:43 +0200311 last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000312 } else {
313 last_frame_capture_time_ms_ = capture_time_ms;
314 }
315}
316
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000317void RTCPSender::SetSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200318 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000319
Erik Språng242e22b2015-05-11 10:17:43 +0200320 if (ssrc_ != 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200321 // not first SetSSRC, probably due to a collision
322 // schedule a new RTCP report
323 // make sure that we send a RTP packet
Erik Språng242e22b2015-05-11 10:17:43 +0200324 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
Erik Språng61be2a42015-04-27 13:32:52 +0200325 }
Erik Språng242e22b2015-05-11 10:17:43 +0200326 ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000327}
328
Erik Språng61be2a42015-04-27 13:32:52 +0200329void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200330 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
331 remote_ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000332}
333
Peter Boström9ba52f82015-06-01 14:12:28 +0200334int32_t RTCPSender::SetCNAME(const char* c_name) {
335 if (!c_name)
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000336 return -1;
337
henrikg91d6ede2015-09-17 00:24:34 -0700338 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
Erik Språng242e22b2015-05-11 10:17:43 +0200339 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200340 cname_ = c_name;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000341 return 0;
342}
343
Erik Språng0ea42d32015-06-25 14:46:16 +0200344int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC, const char* c_name) {
345 assert(c_name);
henrikg91d6ede2015-09-17 00:24:34 -0700346 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
Erik Språng242e22b2015-05-11 10:17:43 +0200347 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200348 if (csrc_cnames_.size() >= kRtpCsrcSize)
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000349 return -1;
Erik Språng0ea42d32015-06-25 14:46:16 +0200350
351 csrc_cnames_[SSRC] = c_name;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000352 return 0;
353}
354
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000355int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
Erik Språng242e22b2015-05-11 10:17:43 +0200356 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200357 auto it = csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000358
Erik Språng242e22b2015-05-11 10:17:43 +0200359 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000360 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200361
Erik Språng242e22b2015-05-11 10:17:43 +0200362 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000363 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000364}
365
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000366bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
danilchap162abd32015-12-10 02:39:40 -0800367 /*
368 For audio we use a fix 5 sec interval
niklase@google.com470e71d2011-07-07 08:21:25 +0000369
danilchap162abd32015-12-10 02:39:40 -0800370 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
371 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
372 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000373
374
danilchap162abd32015-12-10 02:39:40 -0800375 From RFC 3550
niklase@google.com470e71d2011-07-07 08:21:25 +0000376
danilchap162abd32015-12-10 02:39:40 -0800377 MAX RTCP BW is 5% if the session BW
378 A send report is approximately 65 bytes inc CNAME
379 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000380
danilchap162abd32015-12-10 02:39:40 -0800381 The RECOMMENDED value for the reduced minimum in seconds is 360
382 divided by the session bandwidth in kilobits/second. This minimum
383 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
niklase@google.com470e71d2011-07-07 08:21:25 +0000384
danilchap162abd32015-12-10 02:39:40 -0800385 If the participant has not yet sent an RTCP packet (the variable
386 initial is true), the constant Tmin is set to 2.5 seconds, else it
387 is set to 5 seconds.
niklase@google.com470e71d2011-07-07 08:21:25 +0000388
danilchap162abd32015-12-10 02:39:40 -0800389 The interval between RTCP packets is varied randomly over the
390 range [0.5,1.5] times the calculated interval to avoid unintended
391 synchronization of all participants
niklase@google.com470e71d2011-07-07 08:21:25 +0000392
danilchap162abd32015-12-10 02:39:40 -0800393 if we send
394 If the participant is a sender (we_sent true), the constant C is
395 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
396 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
397 number of senders.
niklase@google.com470e71d2011-07-07 08:21:25 +0000398
danilchap162abd32015-12-10 02:39:40 -0800399 if we receive only
400 If we_sent is not true, the constant C is set
401 to the average RTCP packet size divided by 75% of the RTCP
402 bandwidth. The constant n is set to the number of receivers
403 (members - senders). If the number of senders is greater than
404 25%, senders and receivers are treated together.
niklase@google.com470e71d2011-07-07 08:21:25 +0000405
danilchap162abd32015-12-10 02:39:40 -0800406 reconsideration NOT required for peer-to-peer
407 "timer reconsideration" is
408 employed. This algorithm implements a simple back-off mechanism
409 which causes users to hold back RTCP packet transmission if the
410 group sizes are increasing.
niklase@google.com470e71d2011-07-07 08:21:25 +0000411
danilchap162abd32015-12-10 02:39:40 -0800412 n = number of members
413 C = avg_size/(rtcpBW/4)
niklase@google.com470e71d2011-07-07 08:21:25 +0000414
danilchap162abd32015-12-10 02:39:40 -0800415 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
niklase@google.com470e71d2011-07-07 08:21:25 +0000416
danilchap162abd32015-12-10 02:39:40 -0800417 4. The calculated interval T is set to a number uniformly distributed
418 between 0.5 and 1.5 times the deterministic calculated interval.
niklase@google.com470e71d2011-07-07 08:21:25 +0000419
danilchap162abd32015-12-10 02:39:40 -0800420 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
421 for the fact that the timer reconsideration algorithm converges to
422 a value of the RTCP bandwidth below the intended average
423 */
niklase@google.com470e71d2011-07-07 08:21:25 +0000424
Erik Språng242e22b2015-05-11 10:17:43 +0200425 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000426
Erik Språng242e22b2015-05-11 10:17:43 +0200427 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
xians@webrtc.org8738d272011-11-25 13:43:53 +0000428
pbosda903ea2015-10-02 02:36:56 -0700429 if (method_ == RtcpMode::kOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000430 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000431
Erik Språng242e22b2015-05-11 10:17:43 +0200432 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200433 // for video key-frames we want to send the RTCP before the large key-frame
434 // if we have a 100 ms margin
435 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
436 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000437
Erik Språng242e22b2015-05-11 10:17:43 +0200438 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200439 return true;
440 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200441 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200442 // wrap
443 return true;
444 }
445 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000446}
447
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000448int64_t RTCPSender::SendTimeOfSendReport(uint32_t sendReport) {
Erik Språng242e22b2015-05-11 10:17:43 +0200449 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000450
Erik Språng61be2a42015-04-27 13:32:52 +0200451 // This is only saved when we are the sender
Erik Språng242e22b2015-05-11 10:17:43 +0200452 if ((last_send_report_[0] == 0) || (sendReport == 0)) {
Erik Språng61be2a42015-04-27 13:32:52 +0200453 return 0; // will be ignored
454 } else {
455 for (int i = 0; i < RTCP_NUMBER_OF_SR; ++i) {
Erik Språng242e22b2015-05-11 10:17:43 +0200456 if (last_send_report_[i] == sendReport)
457 return last_rtcp_time_[i];
niklase@google.com470e71d2011-07-07 08:21:25 +0000458 }
Erik Språng61be2a42015-04-27 13:32:52 +0200459 }
460 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000461}
462
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000463bool RTCPSender::SendTimeOfXrRrReport(uint32_t mid_ntp,
464 int64_t* time_ms) const {
Erik Språng242e22b2015-05-11 10:17:43 +0200465 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000466
467 if (last_xr_rr_.empty()) {
468 return false;
469 }
470 std::map<uint32_t, int64_t>::const_iterator it = last_xr_rr_.find(mid_ntp);
471 if (it == last_xr_rr_.end()) {
472 return false;
473 }
474 *time_ms = it->second;
475 return true;
476}
477
Erik Språngf7c57762015-12-04 10:40:35 +0100478rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildSR(const RtcpContext& ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200479 for (int i = (RTCP_NUMBER_OF_SR - 2); i >= 0; i--) {
480 // shift old
Erik Språng242e22b2015-05-11 10:17:43 +0200481 last_send_report_[i + 1] = last_send_report_[i];
482 last_rtcp_time_[i + 1] = last_rtcp_time_[i];
Erik Språng61be2a42015-04-27 13:32:52 +0200483 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000484
Erik Språngf7c57762015-12-04 10:40:35 +0100485 last_rtcp_time_[0] = Clock::NtpToMs(ctx.ntp_sec_, ctx.ntp_frac_);
486 last_send_report_[0] = (ctx.ntp_sec_ << 16) + (ctx.ntp_frac_ >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000487
Erik Språng61be2a42015-04-27 13:32:52 +0200488 // The timestamp of this RTCP packet should be estimated as the timestamp of
489 // the frame being captured at this moment. We are calculating that
490 // timestamp as the last frame's timestamp + the time since the last frame
491 // was captured.
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200492 uint32_t rtp_timestamp =
493 start_timestamp_ + last_rtp_timestamp_ +
494 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) *
Erik Språngf7c57762015-12-04 10:40:35 +0100495 (ctx.feedback_state_.frequency_hz / 1000);
niklase@google.com470e71d2011-07-07 08:21:25 +0000496
Erik Språngf7c57762015-12-04 10:40:35 +0100497 rtcp::SenderReport* report = new rtcp::SenderReport();
498 report->From(ssrc_);
danilchap34ed2b92016-01-18 02:43:32 -0800499 report->WithNtp(NtpTime(ctx.ntp_sec_, ctx.ntp_frac_));
Erik Språngf7c57762015-12-04 10:40:35 +0100500 report->WithRtpTimestamp(rtp_timestamp);
501 report->WithPacketCount(ctx.feedback_state_.packets_sent);
502 report->WithOctetCount(ctx.feedback_state_.media_bytes_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000503
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200504 for (auto it : report_blocks_)
Erik Språngf7c57762015-12-04 10:40:35 +0100505 report->WithReportBlock(it.second);
niklase@google.com470e71d2011-07-07 08:21:25 +0000506
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200507 report_blocks_.clear();
Erik Språngf7c57762015-12-04 10:40:35 +0100508
509 return rtc::scoped_ptr<rtcp::SenderReport>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000510}
511
Erik Språngf7c57762015-12-04 10:40:35 +0100512rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildSDES(
513 const RtcpContext& ctx) {
Erik Språng0ea42d32015-06-25 14:46:16 +0200514 size_t length_cname = cname_.length();
henrikg91d6ede2015-09-17 00:24:34 -0700515 RTC_CHECK_LT(length_cname, static_cast<size_t>(RTCP_CNAME_SIZE));
niklase@google.com470e71d2011-07-07 08:21:25 +0000516
Erik Språngf7c57762015-12-04 10:40:35 +0100517 rtcp::Sdes* sdes = new rtcp::Sdes();
518 sdes->WithCName(ssrc_, cname_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200519
520 for (const auto it : csrc_cnames_)
Erik Språngf7c57762015-12-04 10:40:35 +0100521 sdes->WithCName(it.first, it.second);
Erik Språng0ea42d32015-06-25 14:46:16 +0200522
Erik Språngf7c57762015-12-04 10:40:35 +0100523 return rtc::scoped_ptr<rtcp::Sdes>(sdes);
niklase@google.com470e71d2011-07-07 08:21:25 +0000524}
525
Erik Språngf7c57762015-12-04 10:40:35 +0100526rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildRR(const RtcpContext& ctx) {
527 rtcp::ReceiverReport* report = new rtcp::ReceiverReport();
528 report->From(ssrc_);
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200529 for (auto it : report_blocks_)
Erik Språngf7c57762015-12-04 10:40:35 +0100530 report->WithReportBlock(it.second);
Erik Språng61be2a42015-04-27 13:32:52 +0200531
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200532 report_blocks_.clear();
Erik Språngf7c57762015-12-04 10:40:35 +0100533 return rtc::scoped_ptr<rtcp::ReceiverReport>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000534}
535
Erik Språngf7c57762015-12-04 10:40:35 +0100536rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildPLI(const RtcpContext& ctx) {
537 rtcp::Pli* pli = new rtcp::Pli();
538 pli->From(ssrc_);
539 pli->To(remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200540
Erik Språng242e22b2015-05-11 10:17:43 +0200541 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
542 "RTCPSender::PLI");
543 ++packet_type_counter_.pli_packets;
544 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
545 ssrc_, packet_type_counter_.pli_packets);
546
Erik Språngf7c57762015-12-04 10:40:35 +0100547 return rtc::scoped_ptr<rtcp::Pli>(pli);
Erik Språng61be2a42015-04-27 13:32:52 +0200548}
549
Erik Språngf7c57762015-12-04 10:40:35 +0100550rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildFIR(const RtcpContext& ctx) {
551 if (!ctx.repeat_)
sprang62dae192015-08-05 02:35:35 -0700552 ++sequence_number_fir_; // Do not increase if repetition.
niklase@google.com470e71d2011-07-07 08:21:25 +0000553
Erik Språngf7c57762015-12-04 10:40:35 +0100554 rtcp::Fir* fir = new rtcp::Fir();
555 fir->From(ssrc_);
Danil Chapovalov32e590e2016-01-22 11:04:56 +0100556 fir->WithRequestTo(remote_ssrc_, sequence_number_fir_);
Erik Språng242e22b2015-05-11 10:17:43 +0200557
558 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
559 "RTCPSender::FIR");
560 ++packet_type_counter_.fir_packets;
561 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
562 ssrc_, packet_type_counter_.fir_packets);
563
Erik Språngf7c57762015-12-04 10:40:35 +0100564 return rtc::scoped_ptr<rtcp::Fir>(fir);
niklase@google.com470e71d2011-07-07 08:21:25 +0000565}
566
567/*
568 0 1 2 3
569 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
570 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
571 | First | Number | PictureID |
572 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
573*/
Erik Språngf7c57762015-12-04 10:40:35 +0100574rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildSLI(const RtcpContext& ctx) {
575 rtcp::Sli* sli = new rtcp::Sli();
576 sli->From(ssrc_);
577 sli->To(remote_ssrc_);
sprang0365a272015-08-11 01:02:37 -0700578 // Crop picture id to 6 least significant bits.
Erik Språngf7c57762015-12-04 10:40:35 +0100579 sli->WithPictureId(ctx.picture_id_ & 0x3F);
sprang0365a272015-08-11 01:02:37 -0700580
Erik Språngf7c57762015-12-04 10:40:35 +0100581 return rtc::scoped_ptr<rtcp::Sli>(sli);
niklase@google.com470e71d2011-07-07 08:21:25 +0000582}
583
584/*
585 0 1 2 3
586 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
587 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
588 | PB |0| Payload Type| Native RPSI bit string |
589 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
590 | defined per codec ... | Padding (0) |
591 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
592*/
593/*
594* Note: not generic made for VP8
595*/
Erik Språngf7c57762015-12-04 10:40:35 +0100596rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildRPSI(
597 const RtcpContext& ctx) {
598 if (ctx.feedback_state_.send_payload_type == 0xFF)
599 return nullptr;
Erik Språng242e22b2015-05-11 10:17:43 +0200600
Erik Språngf7c57762015-12-04 10:40:35 +0100601 rtcp::Rpsi* rpsi = new rtcp::Rpsi();
602 rpsi->From(ssrc_);
603 rpsi->To(remote_ssrc_);
604 rpsi->WithPayloadType(ctx.feedback_state_.send_payload_type);
605 rpsi->WithPictureId(ctx.picture_id_);
sprangcf7f54d2015-08-13 04:37:42 -0700606
Erik Språngf7c57762015-12-04 10:40:35 +0100607 return rtc::scoped_ptr<rtcp::Rpsi>(rpsi);
niklase@google.com470e71d2011-07-07 08:21:25 +0000608}
609
Erik Språngf7c57762015-12-04 10:40:35 +0100610rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildREMB(
611 const RtcpContext& ctx) {
612 rtcp::Remb* remb = new rtcp::Remb();
613 remb->From(ssrc_);
sprangdd4edc52015-08-21 04:21:51 -0700614 for (uint32_t ssrc : remb_ssrcs_)
Erik Språngf7c57762015-12-04 10:40:35 +0100615 remb->AppliesTo(ssrc);
616 remb->WithBitrateBps(remb_bitrate_);
Erik Språng61be2a42015-04-27 13:32:52 +0200617
Erik Språng242e22b2015-05-11 10:17:43 +0200618 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
619 "RTCPSender::REMB");
620
Erik Språngf7c57762015-12-04 10:40:35 +0100621 return rtc::scoped_ptr<rtcp::Remb>(remb);
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000622}
623
Erik Språng61be2a42015-04-27 13:32:52 +0200624void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
Erik Språng242e22b2015-05-11 10:17:43 +0200625 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
626 tmmbr_send_ = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000627}
628
Erik Språngf7c57762015-12-04 10:40:35 +0100629rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBR(
630 const RtcpContext& ctx) {
631 if (ctx.feedback_state_.module == nullptr)
632 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200633 // Before sending the TMMBR check the received TMMBN, only an owner is
634 // allowed to raise the bitrate:
635 // * If the sender is an owner of the TMMBN -> send TMMBR
636 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000637
Erik Språng61be2a42015-04-27 13:32:52 +0200638 // get current bounding set from RTCP receiver
639 bool tmmbrOwner = false;
640 // store in candidateSet, allocates one extra slot
Erik Språng242e22b2015-05-11 10:17:43 +0200641 TMMBRSet* candidateSet = tmmbr_help_.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000642
Erik Språng242e22b2015-05-11 10:17:43 +0200643 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
644 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
Erik Språng61be2a42015-04-27 13:32:52 +0200645 // since RTCPreceiver is not doing the reverse we should be fine
646 int32_t lengthOfBoundingSet =
danilchap6db6cdc2015-12-15 02:54:47 -0800647 ctx.feedback_state_.module->BoundingSet(&tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +0000648
Erik Språng61be2a42015-04-27 13:32:52 +0200649 if (lengthOfBoundingSet > 0) {
650 for (int32_t i = 0; i < lengthOfBoundingSet; i++) {
Erik Språng242e22b2015-05-11 10:17:43 +0200651 if (candidateSet->Tmmbr(i) == tmmbr_send_ &&
652 candidateSet->PacketOH(i) == packet_oh_send_) {
Erik Språngf7c57762015-12-04 10:40:35 +0100653 // Do not send the same tuple.
654 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200655 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000656 }
Erik Språng61be2a42015-04-27 13:32:52 +0200657 if (!tmmbrOwner) {
658 // use received bounding set as candidate set
659 // add current tuple
Erik Språng242e22b2015-05-11 10:17:43 +0200660 candidateSet->SetEntry(lengthOfBoundingSet, tmmbr_send_, packet_oh_send_,
661 ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200662 int numCandidates = lengthOfBoundingSet + 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000663
Erik Språng61be2a42015-04-27 13:32:52 +0200664 // find bounding set
Erik Språngf7c57762015-12-04 10:40:35 +0100665 TMMBRSet* boundingSet = nullptr;
Erik Språng242e22b2015-05-11 10:17:43 +0200666 int numBoundingSet = tmmbr_help_.FindTMMBRBoundingSet(boundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200667 if (numBoundingSet > 0 || numBoundingSet <= numCandidates)
Erik Språng242e22b2015-05-11 10:17:43 +0200668 tmmbrOwner = tmmbr_help_.IsOwner(ssrc_, numBoundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200669 if (!tmmbrOwner) {
Erik Språngf7c57762015-12-04 10:40:35 +0100670 // Did not enter bounding set, no meaning to send this request.
671 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200672 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000673 }
Erik Språng61be2a42015-04-27 13:32:52 +0200674 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000675
Erik Språngf7c57762015-12-04 10:40:35 +0100676 if (!tmmbr_send_)
677 return nullptr;
sprang81a3e602015-08-21 05:30:11 -0700678
Erik Språngf7c57762015-12-04 10:40:35 +0100679 rtcp::Tmmbr* tmmbr = new rtcp::Tmmbr();
680 tmmbr->From(ssrc_);
danilchapf174e3a2016-02-05 04:56:36 -0800681 rtcp::TmmbItem request;
682 request.set_ssrc(remote_ssrc_);
683 request.set_bitrate_bps(tmmbr_send_ * 1000);
684 request.set_packet_overhead(packet_oh_send_);
685 tmmbr->WithTmmbr(request);
Erik Språngf7c57762015-12-04 10:40:35 +0100686
687 return rtc::scoped_ptr<rtcp::Tmmbr>(tmmbr);
Erik Språng61be2a42015-04-27 13:32:52 +0200688}
689
Erik Språngf7c57762015-12-04 10:40:35 +0100690rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBN(
691 const RtcpContext& ctx) {
Erik Språng242e22b2015-05-11 10:17:43 +0200692 TMMBRSet* boundingSet = tmmbr_help_.BoundingSetToSend();
Erik Språngf7c57762015-12-04 10:40:35 +0100693 if (boundingSet == nullptr)
694 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200695
Erik Språngf7c57762015-12-04 10:40:35 +0100696 rtcp::Tmmbn* tmmbn = new rtcp::Tmmbn();
697 tmmbn->From(ssrc_);
sprangd83df502015-08-27 01:05:08 -0700698 for (uint32_t i = 0; i < boundingSet->lengthOfSet(); i++) {
699 if (boundingSet->Tmmbr(i) > 0) {
Erik Språngf7c57762015-12-04 10:40:35 +0100700 tmmbn->WithTmmbr(boundingSet->Ssrc(i), boundingSet->Tmmbr(i),
701 boundingSet->PacketOH(i));
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000702 }
Erik Språng61be2a42015-04-27 13:32:52 +0200703 }
sprangd83df502015-08-27 01:05:08 -0700704
Erik Språngf7c57762015-12-04 10:40:35 +0100705 return rtc::scoped_ptr<rtcp::Tmmbn>(tmmbn);
niklase@google.com470e71d2011-07-07 08:21:25 +0000706}
707
Erik Språngf7c57762015-12-04 10:40:35 +0100708rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildAPP(const RtcpContext& ctx) {
709 rtcp::App* app = new rtcp::App();
710 app->From(ssrc_);
711 app->WithSubType(app_sub_type_);
712 app->WithName(app_name_);
713 app->WithData(app_data_.get(), app_length_);
Erik Språng521875a2015-09-01 10:11:16 +0200714
Erik Språngf7c57762015-12-04 10:40:35 +0100715 return rtc::scoped_ptr<rtcp::App>(app);
Erik Språng61be2a42015-04-27 13:32:52 +0200716}
717
Erik Språngf7c57762015-12-04 10:40:35 +0100718rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildNACK(
719 const RtcpContext& ctx) {
720 rtcp::Nack* nack = new rtcp::Nack();
721 nack->From(ssrc_);
722 nack->To(remote_ssrc_);
723 nack->WithList(ctx.nack_list_, ctx.nack_size_);
Erik Språng61be2a42015-04-27 13:32:52 +0200724
725 // Report stats.
726 NACKStringBuilder stringBuilder;
Erik Språngf7c57762015-12-04 10:40:35 +0100727 for (int idx = 0; idx < ctx.nack_size_; ++idx) {
728 stringBuilder.PushNACK(ctx.nack_list_[idx]);
729 nack_stats_.ReportRequest(ctx.nack_list_[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +0200730 }
Erik Språng61be2a42015-04-27 13:32:52 +0200731 packet_type_counter_.nack_requests = nack_stats_.requests();
732 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +0200733
734 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
735 "RTCPSender::NACK", "nacks",
736 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
737 ++packet_type_counter_.nack_packets;
738 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
739 ssrc_, packet_type_counter_.nack_packets);
740
Erik Språngf7c57762015-12-04 10:40:35 +0100741 return rtc::scoped_ptr<rtcp::Nack>(nack);
Erik Språng61be2a42015-04-27 13:32:52 +0200742}
743
Erik Språngf7c57762015-12-04 10:40:35 +0100744rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildBYE(const RtcpContext& ctx) {
745 rtcp::Bye* bye = new rtcp::Bye();
746 bye->From(ssrc_);
sprangd8ee4f92015-08-24 03:25:19 -0700747 for (uint32_t csrc : csrcs_)
Erik Språngf7c57762015-12-04 10:40:35 +0100748 bye->WithCsrc(csrc);
sprangd8ee4f92015-08-24 03:25:19 -0700749
Erik Språngf7c57762015-12-04 10:40:35 +0100750 return rtc::scoped_ptr<rtcp::Bye>(bye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000751}
752
Erik Språngf7c57762015-12-04 10:40:35 +0100753rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildReceiverReferenceTime(
754 const RtcpContext& ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200755 if (last_xr_rr_.size() >= RTCP_NUMBER_OF_SR)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000756 last_xr_rr_.erase(last_xr_rr_.begin());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000757 last_xr_rr_.insert(std::pair<uint32_t, int64_t>(
Erik Språngf7c57762015-12-04 10:40:35 +0100758 RTCPUtility::MidNtp(ctx.ntp_sec_, ctx.ntp_frac_),
759 Clock::NtpToMs(ctx.ntp_sec_, ctx.ntp_frac_)));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000760
Danil Chapovalov256e5b22016-01-15 14:16:24 +0100761 rtcp::ExtendedReports* xr = new rtcp::ExtendedReports();
Erik Språngf7c57762015-12-04 10:40:35 +0100762 xr->From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000763
Erik Språngca28fdc2015-08-31 14:00:50 +0200764 rtcp::Rrtr rrtr;
Danil Chapovalovfc47ed62015-12-07 14:46:35 +0100765 rrtr.WithNtp(NtpTime(ctx.ntp_sec_, ctx.ntp_frac_));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000766
danilchapde138822016-01-29 11:26:14 -0800767 xr->WithRrtr(rrtr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000768
Erik Språngca28fdc2015-08-31 14:00:50 +0200769 // TODO(sprang): Merge XR report sending to contain all of RRTR, DLRR, VOIP?
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000770
Danil Chapovalov256e5b22016-01-15 14:16:24 +0100771 return rtc::scoped_ptr<rtcp::RtcpPacket>(xr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000772}
773
Erik Språngf7c57762015-12-04 10:40:35 +0100774rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildDlrr(
775 const RtcpContext& ctx) {
Danil Chapovalov256e5b22016-01-15 14:16:24 +0100776 rtcp::ExtendedReports* xr = new rtcp::ExtendedReports();
Erik Språngf7c57762015-12-04 10:40:35 +0100777 xr->From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000778
Erik Språngca28fdc2015-08-31 14:00:50 +0200779 rtcp::Dlrr dlrr;
Erik Språngf7c57762015-12-04 10:40:35 +0100780 const RtcpReceiveTimeInfo& info = ctx.feedback_state_.last_xr_rr;
Erik Språngca28fdc2015-08-31 14:00:50 +0200781 dlrr.WithDlrrItem(info.sourceSSRC, info.lastRR, info.delaySinceLastRR);
782
danilchapde138822016-01-29 11:26:14 -0800783 xr->WithDlrr(dlrr);
Erik Språngca28fdc2015-08-31 14:00:50 +0200784
Danil Chapovalov256e5b22016-01-15 14:16:24 +0100785 return rtc::scoped_ptr<rtcp::RtcpPacket>(xr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000786}
787
Erik Språng242e22b2015-05-11 10:17:43 +0200788// TODO(sprang): Add a unit test for this, or remove if the code isn't used.
Erik Språngf7c57762015-12-04 10:40:35 +0100789rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildVoIPMetric(
790 const RtcpContext& context) {
Danil Chapovalov256e5b22016-01-15 14:16:24 +0100791 rtcp::ExtendedReports* xr = new rtcp::ExtendedReports();
Erik Språngf7c57762015-12-04 10:40:35 +0100792 xr->From(ssrc_);
Erik Språngca28fdc2015-08-31 14:00:50 +0200793
794 rtcp::VoipMetric voip;
795 voip.To(remote_ssrc_);
danilchap91941ae2015-12-15 07:06:36 -0800796 voip.WithVoipMetric(xr_voip_metric_);
Erik Språngca28fdc2015-08-31 14:00:50 +0200797
danilchapde138822016-01-29 11:26:14 -0800798 xr->WithVoipMetric(voip);
Erik Språngca28fdc2015-08-31 14:00:50 +0200799
Danil Chapovalov256e5b22016-01-15 14:16:24 +0100800 return rtc::scoped_ptr<rtcp::RtcpPacket>(xr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000801}
802
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000803int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200804 RTCPPacketType packetType,
805 int32_t nack_size,
806 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000807 bool repeat,
808 uint64_t pictureID) {
Erik Språng242e22b2015-05-11 10:17:43 +0200809 return SendCompoundRTCP(
810 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
811 nack_size, nack_list, repeat, pictureID);
812}
813
814int32_t RTCPSender::SendCompoundRTCP(
815 const FeedbackState& feedback_state,
Erik Språngf7c57762015-12-04 10:40:35 +0100816 const std::set<RTCPPacketType>& packet_types,
Erik Språng242e22b2015-05-11 10:17:43 +0200817 int32_t nack_size,
818 const uint16_t* nack_list,
819 bool repeat,
820 uint64_t pictureID) {
terelius429c3452016-01-21 05:42:04 -0800821 PacketContainer container(transport_, event_log_);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000822 {
Erik Språng242e22b2015-05-11 10:17:43 +0200823 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
pbosda903ea2015-10-02 02:36:56 -0700824 if (method_ == RtcpMode::kOff) {
Erik Språng61be2a42015-04-27 13:32:52 +0200825 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
826 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +0000827 }
Erik Språngf7c57762015-12-04 10:40:35 +0100828
829 // We need to send our NTP even if we haven't received any reports.
830 uint32_t ntp_sec;
831 uint32_t ntp_frac;
832 clock_->CurrentNtp(ntp_sec, ntp_frac);
833 RtcpContext context(feedback_state, nack_size, nack_list, repeat, pictureID,
834 ntp_sec, ntp_frac, &container);
835
836 PrepareReport(packet_types, feedback_state);
837
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800838 rtc::scoped_ptr<rtcp::RtcpPacket> packet_bye;
839
Erik Språngf7c57762015-12-04 10:40:35 +0100840 auto it = report_flags_.begin();
841 while (it != report_flags_.end()) {
842 auto builder_it = builders_.find(it->type);
843 RTC_DCHECK(builder_it != builders_.end());
844 if (it->is_volatile) {
845 report_flags_.erase(it++);
846 } else {
847 ++it;
848 }
849
850 BuilderFunc func = builder_it->second;
851 rtc::scoped_ptr<rtcp::RtcpPacket> packet = (this->*func)(context);
852 if (packet.get() == nullptr)
853 return -1;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800854 // If there is a BYE, don't append now - save it and append it
855 // at the end later.
856 if (builder_it->first == kRtcpBye) {
857 packet_bye = std::move(packet);
858 } else {
859 container.Append(packet.release());
860 }
861 }
862
863 // Append the BYE now at the end
864 if (packet_bye) {
865 container.Append(packet_bye.release());
Erik Språngf7c57762015-12-04 10:40:35 +0100866 }
867
868 if (packet_type_counter_observer_ != nullptr) {
869 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
870 remote_ssrc_, packet_type_counter_);
871 }
872
873 RTC_DCHECK(AllVolatileFlagsConsumed());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000874 }
Erik Språng61be2a42015-04-27 13:32:52 +0200875
Erik Språngf7c57762015-12-04 10:40:35 +0100876 size_t bytes_sent = container.SendPackets();
877 return bytes_sent == 0 ? -1 : 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000878}
879
Erik Språngf7c57762015-12-04 10:40:35 +0100880void RTCPSender::PrepareReport(const std::set<RTCPPacketType>& packetTypes,
881 const FeedbackState& feedback_state) {
Erik Språng242e22b2015-05-11 10:17:43 +0200882 // Add all flags as volatile. Non volatile entries will not be overwritten
883 // and all new volatile flags added will be consumed by the end of this call.
884 SetFlags(packetTypes, true);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000885
Erik Språng61be2a42015-04-27 13:32:52 +0200886 if (packet_type_counter_.first_packet_time_ms == -1)
Erik Språng242e22b2015-05-11 10:17:43 +0200887 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språng61be2a42015-04-27 13:32:52 +0200888
Erik Språng242e22b2015-05-11 10:17:43 +0200889 bool generate_report;
890 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
891 // Report type already explicitly set, don't automatically populate.
892 generate_report = true;
henrikg91d6ede2015-09-17 00:24:34 -0700893 RTC_DCHECK(ConsumeFlag(kRtcpReport) == false);
Erik Språng242e22b2015-05-11 10:17:43 +0200894 } else {
895 generate_report =
pbosda903ea2015-10-02 02:36:56 -0700896 (ConsumeFlag(kRtcpReport) && method_ == RtcpMode::kReducedSize) ||
897 method_ == RtcpMode::kCompound;
Erik Språng242e22b2015-05-11 10:17:43 +0200898 if (generate_report)
899 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000900 }
901
Erik Språng0ea42d32015-06-25 14:46:16 +0200902 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
Erik Språng242e22b2015-05-11 10:17:43 +0200903 SetFlag(kRtcpSdes, true);
904
Erik Språng242e22b2015-05-11 10:17:43 +0200905 if (generate_report) {
906 if (!sending_ && xr_send_receiver_reference_time_enabled_)
907 SetFlag(kRtcpXrReceiverReferenceTime, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200908 if (feedback_state.has_last_xr_rr)
Erik Språng242e22b2015-05-11 10:17:43 +0200909 SetFlag(kRtcpXrDlrrReportBlock, true);
910
911 // generate next time to send an RTCP report
danilchap47a740b2015-12-15 00:30:07 -0800912 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000913
danilchap47a740b2015-12-15 00:30:07 -0800914 if (!audio_) {
Erik Språng242e22b2015-05-11 10:17:43 +0200915 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200916 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
917 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
918 if (send_bitrate_kbit != 0)
919 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000920 }
Erik Språng61be2a42015-04-27 13:32:52 +0200921 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
922 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
Erik Språng61be2a42015-04-27 13:32:52 +0200923 }
danilchap47a740b2015-12-15 00:30:07 -0800924 // The interval between RTCP packets is varied randomly over the
925 // range [1/2,3/2] times the calculated interval.
926 uint32_t timeToNext =
927 random_.Rand(minIntervalMs * 1 / 2, minIntervalMs * 3 / 2);
Erik Språng242e22b2015-05-11 10:17:43 +0200928 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000929
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000930 StatisticianMap statisticians =
931 receive_statistics_->GetActiveStatisticians();
danilchapa72e7342015-12-22 08:07:45 -0800932 RTC_DCHECK(report_blocks_.empty());
933 for (auto& it : statisticians) {
934 AddReportBlock(feedback_state, it.first, it.second);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000935 }
936 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000937}
938
danilchapa72e7342015-12-22 08:07:45 -0800939bool RTCPSender::AddReportBlock(const FeedbackState& feedback_state,
940 uint32_t ssrc,
941 StreamStatistician* statistician) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000942 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000943 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000944 if (!statistician->GetStatistics(&stats, true))
945 return false;
danilchapa72e7342015-12-22 08:07:45 -0800946
947 if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) {
948 LOG(LS_WARNING) << "Too many report blocks.";
949 return false;
950 }
951 RTC_DCHECK(report_blocks_.find(ssrc) == report_blocks_.end());
952 rtcp::ReportBlock* block = &report_blocks_[ssrc];
953 block->To(ssrc);
954 block->WithFractionLost(stats.fraction_lost);
955 if (!block->WithCumulativeLost(stats.cumulative_lost)) {
956 report_blocks_.erase(ssrc);
957 LOG(LS_WARNING) << "Cumulative lost is oversized.";
958 return false;
959 }
960 block->WithExtHighestSeqNum(stats.extended_max_sequence_number);
961 block->WithJitter(stats.jitter);
962 block->WithLastSr(feedback_state.remote_sr);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000963
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200964 // TODO(sprang): Do we really need separate time stamps for each report?
965 // Get our NTP as late as possible to avoid a race.
966 uint32_t ntp_secs;
967 uint32_t ntp_frac;
968 clock_->CurrentNtp(ntp_secs, ntp_frac);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000969
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200970 // Delay since last received report.
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000971 if ((feedback_state.last_rr_ntp_secs != 0) ||
972 (feedback_state.last_rr_ntp_frac != 0)) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200973 // Get the 16 lowest bits of seconds and the 16 highest bits of fractions.
974 uint32_t now = ntp_secs & 0x0000FFFF;
Erik Språng61be2a42015-04-27 13:32:52 +0200975 now <<= 16;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200976 now += (ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000977
Erik Språng61be2a42015-04-27 13:32:52 +0200978 uint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
979 receiveTime <<= 16;
980 receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000981
danilchapa72e7342015-12-22 08:07:45 -0800982 block->WithDelayLastSr(now - receiveTime);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000983 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000984 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000985}
986
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000987void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
988 assert(csrcs.size() <= kRtpCsrcSize);
Erik Språng242e22b2015-05-11 10:17:43 +0200989 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000990 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +0000991}
992
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000993int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
994 uint32_t name,
995 const uint8_t* data,
996 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +0200997 if (length % 4 != 0) {
998 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
999 return -1;
1000 }
Erik Språng242e22b2015-05-11 10:17:43 +02001001 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +00001002
Erik Språng242e22b2015-05-11 10:17:43 +02001003 SetFlag(kRtcpApp, true);
1004 app_sub_type_ = subType;
1005 app_name_ = name;
1006 app_data_.reset(new uint8_t[length]);
1007 app_length_ = length;
1008 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +02001009 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001010}
1011
Erik Språng61be2a42015-04-27 13:32:52 +02001012int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
Erik Språng242e22b2015-05-11 10:17:43 +02001013 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1014 memcpy(&xr_voip_metric_, VoIPMetric, sizeof(RTCPVoIPMetric));
niklase@google.com470e71d2011-07-07 08:21:25 +00001015
Erik Språng242e22b2015-05-11 10:17:43 +02001016 SetFlag(kRtcpXrVoipMetric, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001017 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001018}
1019
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001020void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +02001021 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1022 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001023}
1024
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00001025bool RTCPSender::RtcpXrReceiverReferenceTime() const {
Erik Språng242e22b2015-05-11 10:17:43 +02001026 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1027 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00001028}
1029
niklase@google.com470e71d2011-07-07 08:21:25 +00001030// no callbacks allowed inside this function
Peter Boström9d0c4322016-02-16 17:59:27 +01001031int32_t RTCPSender::SetTMMBN(const TMMBRSet* boundingSet) {
Erik Språng242e22b2015-05-11 10:17:43 +02001032 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +00001033
Peter Boström9d0c4322016-02-16 17:59:27 +01001034 if (0 == tmmbr_help_.SetTMMBRBoundingSetToSend(boundingSet)) {
Erik Språng242e22b2015-05-11 10:17:43 +02001035 SetFlag(kRtcpTmmbn, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001036 return 0;
1037 }
1038 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001039}
Erik Språng61be2a42015-04-27 13:32:52 +02001040
Erik Språng242e22b2015-05-11 10:17:43 +02001041void RTCPSender::SetFlag(RTCPPacketType type, bool is_volatile) {
1042 report_flags_.insert(ReportFlag(type, is_volatile));
1043}
1044
1045void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
1046 bool is_volatile) {
1047 for (RTCPPacketType type : types)
1048 SetFlag(type, is_volatile);
1049}
1050
1051bool RTCPSender::IsFlagPresent(RTCPPacketType type) const {
1052 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
1053}
1054
1055bool RTCPSender::ConsumeFlag(RTCPPacketType type, bool forced) {
1056 auto it = report_flags_.find(ReportFlag(type, false));
1057 if (it == report_flags_.end())
1058 return false;
1059 if (it->is_volatile || forced)
1060 report_flags_.erase((it));
1061 return true;
1062}
1063
1064bool RTCPSender::AllVolatileFlagsConsumed() const {
1065 for (const ReportFlag& flag : report_flags_) {
1066 if (flag.is_volatile)
1067 return false;
1068 }
1069 return true;
1070}
1071
sprang233bd872015-09-08 13:25:16 -07001072bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
sprang233bd872015-09-08 13:25:16 -07001073 class Sender : public rtcp::RtcpPacket::PacketReadyCallback {
1074 public:
terelius429c3452016-01-21 05:42:04 -08001075 Sender(Transport* transport, RtcEventLog* event_log)
1076 : transport_(transport), event_log_(event_log), send_failure_(false) {}
sprang233bd872015-09-08 13:25:16 -07001077
1078 void OnPacketReady(uint8_t* data, size_t length) override {
terelius429c3452016-01-21 05:42:04 -08001079 if (transport_->SendRtcp(data, length)) {
1080 if (event_log_) {
1081 event_log_->LogRtcpPacket(kOutgoingPacket, MediaType::ANY, data,
1082 length);
1083 }
1084 } else {
sprang233bd872015-09-08 13:25:16 -07001085 send_failure_ = true;
terelius429c3452016-01-21 05:42:04 -08001086 }
sprang233bd872015-09-08 13:25:16 -07001087 }
1088
1089 Transport* const transport_;
terelius429c3452016-01-21 05:42:04 -08001090 RtcEventLog* const event_log_;
sprang233bd872015-09-08 13:25:16 -07001091 bool send_failure_;
terelius429c3452016-01-21 05:42:04 -08001092 // TODO(terelius): We would like to
1093 // RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(Sender);
1094 // but we can't because of an incorrect warning (C4822) in MVS 2013.
1095 } sender(transport_, event_log_);
sprang233bd872015-09-08 13:25:16 -07001096
1097 uint8_t buffer[IP_PACKET_SIZE];
1098 return packet.BuildExternalBuffer(buffer, IP_PACKET_SIZE, &sender) &&
1099 !sender.send_failure_;
1100}
1101
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001102} // namespace webrtc