blob: 7f5a1fef20e11737b7a48f4815fc4c7585615db1 [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
838 auto it = report_flags_.begin();
839 while (it != report_flags_.end()) {
840 auto builder_it = builders_.find(it->type);
841 RTC_DCHECK(builder_it != builders_.end());
842 if (it->is_volatile) {
843 report_flags_.erase(it++);
844 } else {
845 ++it;
846 }
847
848 BuilderFunc func = builder_it->second;
849 rtc::scoped_ptr<rtcp::RtcpPacket> packet = (this->*func)(context);
850 if (packet.get() == nullptr)
851 return -1;
852 container.Append(packet.release());
853 }
854
855 if (packet_type_counter_observer_ != nullptr) {
856 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
857 remote_ssrc_, packet_type_counter_);
858 }
859
860 RTC_DCHECK(AllVolatileFlagsConsumed());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000861 }
Erik Språng61be2a42015-04-27 13:32:52 +0200862
Erik Språngf7c57762015-12-04 10:40:35 +0100863 size_t bytes_sent = container.SendPackets();
864 return bytes_sent == 0 ? -1 : 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000865}
866
Erik Språngf7c57762015-12-04 10:40:35 +0100867void RTCPSender::PrepareReport(const std::set<RTCPPacketType>& packetTypes,
868 const FeedbackState& feedback_state) {
Erik Språng242e22b2015-05-11 10:17:43 +0200869 // Add all flags as volatile. Non volatile entries will not be overwritten
870 // and all new volatile flags added will be consumed by the end of this call.
871 SetFlags(packetTypes, true);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000872
Erik Språng61be2a42015-04-27 13:32:52 +0200873 if (packet_type_counter_.first_packet_time_ms == -1)
Erik Språng242e22b2015-05-11 10:17:43 +0200874 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språng61be2a42015-04-27 13:32:52 +0200875
Erik Språng242e22b2015-05-11 10:17:43 +0200876 bool generate_report;
877 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
878 // Report type already explicitly set, don't automatically populate.
879 generate_report = true;
henrikg91d6ede2015-09-17 00:24:34 -0700880 RTC_DCHECK(ConsumeFlag(kRtcpReport) == false);
Erik Språng242e22b2015-05-11 10:17:43 +0200881 } else {
882 generate_report =
pbosda903ea2015-10-02 02:36:56 -0700883 (ConsumeFlag(kRtcpReport) && method_ == RtcpMode::kReducedSize) ||
884 method_ == RtcpMode::kCompound;
Erik Språng242e22b2015-05-11 10:17:43 +0200885 if (generate_report)
886 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000887 }
888
Erik Språng0ea42d32015-06-25 14:46:16 +0200889 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
Erik Språng242e22b2015-05-11 10:17:43 +0200890 SetFlag(kRtcpSdes, true);
891
Erik Språng242e22b2015-05-11 10:17:43 +0200892 if (generate_report) {
893 if (!sending_ && xr_send_receiver_reference_time_enabled_)
894 SetFlag(kRtcpXrReceiverReferenceTime, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200895 if (feedback_state.has_last_xr_rr)
Erik Språng242e22b2015-05-11 10:17:43 +0200896 SetFlag(kRtcpXrDlrrReportBlock, true);
897
898 // generate next time to send an RTCP report
danilchap47a740b2015-12-15 00:30:07 -0800899 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000900
danilchap47a740b2015-12-15 00:30:07 -0800901 if (!audio_) {
Erik Språng242e22b2015-05-11 10:17:43 +0200902 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200903 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
904 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
905 if (send_bitrate_kbit != 0)
906 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000907 }
Erik Språng61be2a42015-04-27 13:32:52 +0200908 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
909 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
Erik Språng61be2a42015-04-27 13:32:52 +0200910 }
danilchap47a740b2015-12-15 00:30:07 -0800911 // The interval between RTCP packets is varied randomly over the
912 // range [1/2,3/2] times the calculated interval.
913 uint32_t timeToNext =
914 random_.Rand(minIntervalMs * 1 / 2, minIntervalMs * 3 / 2);
Erik Språng242e22b2015-05-11 10:17:43 +0200915 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000916
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000917 StatisticianMap statisticians =
918 receive_statistics_->GetActiveStatisticians();
danilchapa72e7342015-12-22 08:07:45 -0800919 RTC_DCHECK(report_blocks_.empty());
920 for (auto& it : statisticians) {
921 AddReportBlock(feedback_state, it.first, it.second);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000922 }
923 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000924}
925
danilchapa72e7342015-12-22 08:07:45 -0800926bool RTCPSender::AddReportBlock(const FeedbackState& feedback_state,
927 uint32_t ssrc,
928 StreamStatistician* statistician) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000929 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000930 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000931 if (!statistician->GetStatistics(&stats, true))
932 return false;
danilchapa72e7342015-12-22 08:07:45 -0800933
934 if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) {
935 LOG(LS_WARNING) << "Too many report blocks.";
936 return false;
937 }
938 RTC_DCHECK(report_blocks_.find(ssrc) == report_blocks_.end());
939 rtcp::ReportBlock* block = &report_blocks_[ssrc];
940 block->To(ssrc);
941 block->WithFractionLost(stats.fraction_lost);
942 if (!block->WithCumulativeLost(stats.cumulative_lost)) {
943 report_blocks_.erase(ssrc);
944 LOG(LS_WARNING) << "Cumulative lost is oversized.";
945 return false;
946 }
947 block->WithExtHighestSeqNum(stats.extended_max_sequence_number);
948 block->WithJitter(stats.jitter);
949 block->WithLastSr(feedback_state.remote_sr);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000950
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200951 // TODO(sprang): Do we really need separate time stamps for each report?
952 // Get our NTP as late as possible to avoid a race.
953 uint32_t ntp_secs;
954 uint32_t ntp_frac;
955 clock_->CurrentNtp(ntp_secs, ntp_frac);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000956
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200957 // Delay since last received report.
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000958 if ((feedback_state.last_rr_ntp_secs != 0) ||
959 (feedback_state.last_rr_ntp_frac != 0)) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200960 // Get the 16 lowest bits of seconds and the 16 highest bits of fractions.
961 uint32_t now = ntp_secs & 0x0000FFFF;
Erik Språng61be2a42015-04-27 13:32:52 +0200962 now <<= 16;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200963 now += (ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000964
Erik Språng61be2a42015-04-27 13:32:52 +0200965 uint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
966 receiveTime <<= 16;
967 receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000968
danilchapa72e7342015-12-22 08:07:45 -0800969 block->WithDelayLastSr(now - receiveTime);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000970 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000971 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000972}
973
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000974void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
975 assert(csrcs.size() <= kRtpCsrcSize);
Erik Språng242e22b2015-05-11 10:17:43 +0200976 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000977 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +0000978}
979
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000980int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
981 uint32_t name,
982 const uint8_t* data,
983 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +0200984 if (length % 4 != 0) {
985 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
986 return -1;
987 }
Erik Språng242e22b2015-05-11 10:17:43 +0200988 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000989
Erik Språng242e22b2015-05-11 10:17:43 +0200990 SetFlag(kRtcpApp, true);
991 app_sub_type_ = subType;
992 app_name_ = name;
993 app_data_.reset(new uint8_t[length]);
994 app_length_ = length;
995 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +0200996 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000997}
998
Erik Språng61be2a42015-04-27 13:32:52 +0200999int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
Erik Språng242e22b2015-05-11 10:17:43 +02001000 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1001 memcpy(&xr_voip_metric_, VoIPMetric, sizeof(RTCPVoIPMetric));
niklase@google.com470e71d2011-07-07 08:21:25 +00001002
Erik Språng242e22b2015-05-11 10:17:43 +02001003 SetFlag(kRtcpXrVoipMetric, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001004 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001005}
1006
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001007void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +02001008 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1009 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001010}
1011
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00001012bool RTCPSender::RtcpXrReceiverReferenceTime() const {
Erik Språng242e22b2015-05-11 10:17:43 +02001013 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1014 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00001015}
1016
niklase@google.com470e71d2011-07-07 08:21:25 +00001017// no callbacks allowed inside this function
Peter Boström9d0c4322016-02-16 17:59:27 +01001018int32_t RTCPSender::SetTMMBN(const TMMBRSet* boundingSet) {
Erik Språng242e22b2015-05-11 10:17:43 +02001019 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +00001020
Peter Boström9d0c4322016-02-16 17:59:27 +01001021 if (0 == tmmbr_help_.SetTMMBRBoundingSetToSend(boundingSet)) {
Erik Språng242e22b2015-05-11 10:17:43 +02001022 SetFlag(kRtcpTmmbn, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001023 return 0;
1024 }
1025 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001026}
Erik Språng61be2a42015-04-27 13:32:52 +02001027
Erik Språng242e22b2015-05-11 10:17:43 +02001028void RTCPSender::SetFlag(RTCPPacketType type, bool is_volatile) {
1029 report_flags_.insert(ReportFlag(type, is_volatile));
1030}
1031
1032void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
1033 bool is_volatile) {
1034 for (RTCPPacketType type : types)
1035 SetFlag(type, is_volatile);
1036}
1037
1038bool RTCPSender::IsFlagPresent(RTCPPacketType type) const {
1039 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
1040}
1041
1042bool RTCPSender::ConsumeFlag(RTCPPacketType type, bool forced) {
1043 auto it = report_flags_.find(ReportFlag(type, false));
1044 if (it == report_flags_.end())
1045 return false;
1046 if (it->is_volatile || forced)
1047 report_flags_.erase((it));
1048 return true;
1049}
1050
1051bool RTCPSender::AllVolatileFlagsConsumed() const {
1052 for (const ReportFlag& flag : report_flags_) {
1053 if (flag.is_volatile)
1054 return false;
1055 }
1056 return true;
1057}
1058
sprang233bd872015-09-08 13:25:16 -07001059bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
sprang233bd872015-09-08 13:25:16 -07001060 class Sender : public rtcp::RtcpPacket::PacketReadyCallback {
1061 public:
terelius429c3452016-01-21 05:42:04 -08001062 Sender(Transport* transport, RtcEventLog* event_log)
1063 : transport_(transport), event_log_(event_log), send_failure_(false) {}
sprang233bd872015-09-08 13:25:16 -07001064
1065 void OnPacketReady(uint8_t* data, size_t length) override {
terelius429c3452016-01-21 05:42:04 -08001066 if (transport_->SendRtcp(data, length)) {
1067 if (event_log_) {
1068 event_log_->LogRtcpPacket(kOutgoingPacket, MediaType::ANY, data,
1069 length);
1070 }
1071 } else {
sprang233bd872015-09-08 13:25:16 -07001072 send_failure_ = true;
terelius429c3452016-01-21 05:42:04 -08001073 }
sprang233bd872015-09-08 13:25:16 -07001074 }
1075
1076 Transport* const transport_;
terelius429c3452016-01-21 05:42:04 -08001077 RtcEventLog* const event_log_;
sprang233bd872015-09-08 13:25:16 -07001078 bool send_failure_;
terelius429c3452016-01-21 05:42:04 -08001079 // TODO(terelius): We would like to
1080 // RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(Sender);
1081 // but we can't because of an incorrect warning (C4822) in MVS 2013.
1082 } sender(transport_, event_log_);
sprang233bd872015-09-08 13:25:16 -07001083
1084 uint8_t buffer[IP_PACKET_SIZE];
1085 return packet.BuildExternalBuffer(buffer, IP_PACKET_SIZE, &sender) &&
1086 !sender.send_failure_;
1087}
1088
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001089} // namespace webrtc