blob: 9f3e66e58d82b8f46ab4e0d2934e2556b8301964 [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
14#include <stdlib.h> // rand
stefan@webrtc.org9354cc92012-06-07 08:10:14 +000015#include <string.h> // memcpy
niklase@google.com470e71d2011-07-07 08:21:25 +000016
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000017#include <algorithm> // min
Erik Språng61be2a42015-04-27 13:32:52 +020018#include <limits> // max
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"
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000023#include "webrtc/common_types.h"
sprang@webrtc.org779c3d12015-03-17 16:42:49 +000024#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
danilchap0219c9b2015-11-18 05:56:53 -080025#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/app.h"
danilchap50c51362015-11-22 09:03:11 -080026#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/bye.h"
danilchapf8385ad2015-11-27 05:36:09 -080027#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/pli.h"
Danil Chapovalov97f7e132015-12-04 16:13:30 +010028#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
sprang233bd872015-09-08 13:25:16 -070029#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
tommie4f96502015-10-20 23:00:48 -070030#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010031#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000032
niklase@google.com470e71d2011-07-07 08:21:25 +000033namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000034
35using RTCPUtility::RTCPCnameInformation;
36
Erik Språng61be2a42015-04-27 13:32:52 +020037NACKStringBuilder::NACKStringBuilder()
danilchap162abd32015-12-10 02:39:40 -080038 : stream_(""), count_(0), prevNack_(0), consecutive_(false) {}
edjee@google.com79b02892013-04-04 19:43:34 +000039
pbos@webrtc.orgf3e4cee2013-07-31 15:17:19 +000040NACKStringBuilder::~NACKStringBuilder() {}
41
danilchap162abd32015-12-10 02:39:40 -080042void NACKStringBuilder::PushNACK(uint16_t nack) {
Erik Språng242e22b2015-05-11 10:17:43 +020043 if (count_ == 0) {
44 stream_ << nack;
45 } else if (nack == prevNack_ + 1) {
46 consecutive_ = true;
Erik Språng61be2a42015-04-27 13:32:52 +020047 } else {
Erik Språng242e22b2015-05-11 10:17:43 +020048 if (consecutive_) {
49 stream_ << "-" << prevNack_;
50 consecutive_ = false;
edjee@google.com79b02892013-04-04 19:43:34 +000051 }
Erik Språng242e22b2015-05-11 10:17:43 +020052 stream_ << "," << nack;
Erik Språng61be2a42015-04-27 13:32:52 +020053 }
Erik Språng242e22b2015-05-11 10:17:43 +020054 count_++;
55 prevNack_ = nack;
edjee@google.com79b02892013-04-04 19:43:34 +000056}
57
Erik Språng61be2a42015-04-27 13:32:52 +020058std::string NACKStringBuilder::GetResult() {
Erik Språng242e22b2015-05-11 10:17:43 +020059 if (consecutive_) {
60 stream_ << "-" << prevNack_;
61 consecutive_ = false;
Erik Språng61be2a42015-04-27 13:32:52 +020062 }
Erik Språng242e22b2015-05-11 10:17:43 +020063 return stream_.str();
edjee@google.com79b02892013-04-04 19:43:34 +000064}
65
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000066RTCPSender::FeedbackState::FeedbackState()
67 : send_payload_type(0),
68 frequency_hz(0),
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +000069 packets_sent(0),
70 media_bytes_sent(0),
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000071 send_bitrate(0),
72 last_rr_ntp_secs(0),
73 last_rr_ntp_frac(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000074 remote_sr(0),
Erik Språng61be2a42015-04-27 13:32:52 +020075 has_last_xr_rr(false),
danilchap162abd32015-12-10 02:39:40 -080076 module(nullptr) {}
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000077
Erik Språngf7c57762015-12-04 10:40:35 +010078class PacketContainer : public rtcp::Empty,
79 public rtcp::RtcpPacket::PacketReadyCallback {
80 public:
81 explicit PacketContainer(Transport* transport)
82 : transport_(transport), bytes_sent_(0) {}
83 virtual ~PacketContainer() {
84 for (RtcpPacket* packet : appended_packets_)
85 delete packet;
86 }
87
88 void OnPacketReady(uint8_t* data, size_t length) override {
89 if (transport_->SendRtcp(data, length))
90 bytes_sent_ += length;
91 }
92
93 size_t SendPackets() {
94 rtcp::Empty::Build(this);
95 return bytes_sent_;
96 }
97
98 private:
99 Transport* transport_;
100 size_t bytes_sent_;
101};
102
103class RTCPSender::RtcpContext {
104 public:
Erik Språng242e22b2015-05-11 10:17:43 +0200105 RtcpContext(const FeedbackState& feedback_state,
106 int32_t nack_size,
107 const uint16_t* nack_list,
108 bool repeat,
109 uint64_t picture_id,
Erik Språngf7c57762015-12-04 10:40:35 +0100110 uint32_t ntp_sec,
111 uint32_t ntp_frac,
112 PacketContainer* container)
113 : feedback_state_(feedback_state),
114 nack_size_(nack_size),
115 nack_list_(nack_list),
116 repeat_(repeat),
117 picture_id_(picture_id),
118 ntp_sec_(ntp_sec),
119 ntp_frac_(ntp_frac),
120 container_(container) {}
Erik Språng242e22b2015-05-11 10:17:43 +0200121
Erik Språngf7c57762015-12-04 10:40:35 +0100122 virtual ~RtcpContext() {}
Erik Språng242e22b2015-05-11 10:17:43 +0200123
Erik Språngf7c57762015-12-04 10:40:35 +0100124 const FeedbackState& feedback_state_;
125 const int32_t nack_size_;
126 const uint16_t* nack_list_;
127 const bool repeat_;
128 const uint64_t picture_id_;
129 const uint32_t ntp_sec_;
130 const uint32_t ntp_frac_;
Erik Språng242e22b2015-05-11 10:17:43 +0200131
Erik Språngf7c57762015-12-04 10:40:35 +0100132 PacketContainer* const container_;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200133};
134
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000135RTCPSender::RTCPSender(
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000136 bool audio,
137 Clock* clock,
138 ReceiveStatistics* receive_statistics,
sprang86fd9ed2015-09-29 04:45:43 -0700139 RtcpPacketTypeCounterObserver* packet_type_counter_observer,
140 Transport* outgoing_transport)
Peter Boströmac547a62015-09-17 23:03:57 +0200141 : audio_(audio),
Erik Språng242e22b2015-05-11 10:17:43 +0200142 clock_(clock),
pbosda903ea2015-10-02 02:36:56 -0700143 method_(RtcpMode::kOff),
sprang86fd9ed2015-09-29 04:45:43 -0700144 transport_(outgoing_transport),
niklase@google.com470e71d2011-07-07 08:21:25 +0000145
Erik Språng242e22b2015-05-11 10:17:43 +0200146 critical_section_rtcp_sender_(
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000147 CriticalSectionWrapper::CreateCriticalSection()),
Erik Språng242e22b2015-05-11 10:17:43 +0200148 using_nack_(false),
149 sending_(false),
150 remb_enabled_(false),
Erik Språng242e22b2015-05-11 10:17:43 +0200151 next_time_to_send_rtcp_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000152 start_timestamp_(0),
153 last_rtp_timestamp_(0),
154 last_frame_capture_time_ms_(-1),
Erik Språng242e22b2015-05-11 10:17:43 +0200155 ssrc_(0),
156 remote_ssrc_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000157 receive_statistics_(receive_statistics),
niklase@google.com470e71d2011-07-07 08:21:25 +0000158
Erik Språng242e22b2015-05-11 10:17:43 +0200159 sequence_number_fir_(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000160
Erik Språng242e22b2015-05-11 10:17:43 +0200161 remb_bitrate_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000162
Erik Språng242e22b2015-05-11 10:17:43 +0200163 tmmbr_help_(),
164 tmmbr_send_(0),
165 packet_oh_send_(0),
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000166
Erik Språng242e22b2015-05-11 10:17:43 +0200167 app_sub_type_(0),
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200168 app_name_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200169 app_data_(nullptr),
170 app_length_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000171
Erik Språng242e22b2015-05-11 10:17:43 +0200172 xr_send_receiver_reference_time_enabled_(false),
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000173 packet_type_counter_observer_(packet_type_counter_observer) {
Erik Språng242e22b2015-05-11 10:17:43 +0200174 memset(last_send_report_, 0, sizeof(last_send_report_));
175 memset(last_rtcp_time_, 0, sizeof(last_rtcp_time_));
sprang86fd9ed2015-09-29 04:45:43 -0700176 RTC_DCHECK(transport_ != nullptr);
Erik Språng242e22b2015-05-11 10:17:43 +0200177
178 builders_[kRtcpSr] = &RTCPSender::BuildSR;
179 builders_[kRtcpRr] = &RTCPSender::BuildRR;
Erik Språng0ea42d32015-06-25 14:46:16 +0200180 builders_[kRtcpSdes] = &RTCPSender::BuildSDES;
Erik Språng242e22b2015-05-11 10:17:43 +0200181 builders_[kRtcpPli] = &RTCPSender::BuildPLI;
182 builders_[kRtcpFir] = &RTCPSender::BuildFIR;
183 builders_[kRtcpSli] = &RTCPSender::BuildSLI;
184 builders_[kRtcpRpsi] = &RTCPSender::BuildRPSI;
185 builders_[kRtcpRemb] = &RTCPSender::BuildREMB;
186 builders_[kRtcpBye] = &RTCPSender::BuildBYE;
187 builders_[kRtcpApp] = &RTCPSender::BuildAPP;
188 builders_[kRtcpTmmbr] = &RTCPSender::BuildTMMBR;
189 builders_[kRtcpTmmbn] = &RTCPSender::BuildTMMBN;
190 builders_[kRtcpNack] = &RTCPSender::BuildNACK;
191 builders_[kRtcpXrVoipMetric] = &RTCPSender::BuildVoIPMetric;
192 builders_[kRtcpXrReceiverReferenceTime] =
193 &RTCPSender::BuildReceiverReferenceTime;
194 builders_[kRtcpXrDlrrReportBlock] = &RTCPSender::BuildDlrr;
niklase@google.com470e71d2011-07-07 08:21:25 +0000195}
196
danilchap162abd32015-12-10 02:39:40 -0800197RTCPSender::~RTCPSender() {}
niklase@google.com470e71d2011-07-07 08:21:25 +0000198
pbosda903ea2015-10-02 02:36:56 -0700199RtcpMode RTCPSender::Status() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200200 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
201 return method_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000202}
203
pbosda903ea2015-10-02 02:36:56 -0700204void RTCPSender::SetRTCPStatus(RtcpMode method) {
Erik Språng242e22b2015-05-11 10:17:43 +0200205 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
206 method_ = method;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000207
pbosda903ea2015-10-02 02:36:56 -0700208 if (method == RtcpMode::kOff)
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000209 return;
Erik Språng242e22b2015-05-11 10:17:43 +0200210 next_time_to_send_rtcp_ =
211 clock_->TimeInMilliseconds() +
212 (audio_ ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000213}
214
Erik Språng61be2a42015-04-27 13:32:52 +0200215bool RTCPSender::Sending() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200216 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
217 return sending_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000218}
219
Erik Språng61be2a42015-04-27 13:32:52 +0200220int32_t RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
221 bool sending) {
222 bool sendRTCPBye = false;
223 {
Erik Språng242e22b2015-05-11 10:17:43 +0200224 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000225
pbosda903ea2015-10-02 02:36:56 -0700226 if (method_ != RtcpMode::kOff) {
Erik Språng242e22b2015-05-11 10:17:43 +0200227 if (sending == false && sending_ == true) {
Erik Språng61be2a42015-04-27 13:32:52 +0200228 // Trigger RTCP bye
229 sendRTCPBye = true;
230 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000231 }
Erik Språng242e22b2015-05-11 10:17:43 +0200232 sending_ = sending;
Erik Språng61be2a42015-04-27 13:32:52 +0200233 }
234 if (sendRTCPBye)
235 return SendRTCP(feedback_state, kRtcpBye);
236 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000237}
238
Erik Språng61be2a42015-04-27 13:32:52 +0200239bool RTCPSender::REMB() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200240 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
241 return remb_enabled_;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000242}
243
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000244void RTCPSender::SetREMBStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200245 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
246 remb_enabled_ = enable;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000247}
248
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000249void RTCPSender::SetREMBData(uint32_t bitrate,
250 const std::vector<uint32_t>& ssrcs) {
Erik Språng242e22b2015-05-11 10:17:43 +0200251 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
252 remb_bitrate_ = bitrate;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000253 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000254
Erik Språng242e22b2015-05-11 10:17:43 +0200255 if (remb_enabled_)
256 SetFlag(kRtcpRemb, false);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000257 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
258 // throttled by the caller.
Erik Språng242e22b2015-05-11 10:17:43 +0200259 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000260}
261
Erik Språng61be2a42015-04-27 13:32:52 +0200262bool RTCPSender::TMMBR() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200263 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
264 return IsFlagPresent(RTCPPacketType::kRtcpTmmbr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000265}
266
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000267void RTCPSender::SetTMMBRStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200268 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
269 if (enable) {
270 SetFlag(RTCPPacketType::kRtcpTmmbr, false);
271 } else {
272 ConsumeFlag(RTCPPacketType::kRtcpTmmbr, true);
273 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000274}
275
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000276void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
Erik Språng242e22b2015-05-11 10:17:43 +0200277 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000278 start_timestamp_ = start_timestamp;
279}
280
281void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
282 int64_t capture_time_ms) {
Erik Språng242e22b2015-05-11 10:17:43 +0200283 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000284 last_rtp_timestamp_ = rtp_timestamp;
285 if (capture_time_ms < 0) {
286 // We don't currently get a capture time from VoiceEngine.
Erik Språng242e22b2015-05-11 10:17:43 +0200287 last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000288 } else {
289 last_frame_capture_time_ms_ = capture_time_ms;
290 }
291}
292
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000293void RTCPSender::SetSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200294 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000295
Erik Språng242e22b2015-05-11 10:17:43 +0200296 if (ssrc_ != 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200297 // not first SetSSRC, probably due to a collision
298 // schedule a new RTCP report
299 // make sure that we send a RTP packet
Erik Språng242e22b2015-05-11 10:17:43 +0200300 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
Erik Språng61be2a42015-04-27 13:32:52 +0200301 }
Erik Språng242e22b2015-05-11 10:17:43 +0200302 ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000303}
304
Erik Språng61be2a42015-04-27 13:32:52 +0200305void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200306 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
307 remote_ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000308}
309
Peter Boström9ba52f82015-06-01 14:12:28 +0200310int32_t RTCPSender::SetCNAME(const char* c_name) {
311 if (!c_name)
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000312 return -1;
313
henrikg91d6ede2015-09-17 00:24:34 -0700314 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
Erik Språng242e22b2015-05-11 10:17:43 +0200315 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200316 cname_ = c_name;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000317 return 0;
318}
319
Erik Språng0ea42d32015-06-25 14:46:16 +0200320int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC, const char* c_name) {
321 assert(c_name);
henrikg91d6ede2015-09-17 00:24:34 -0700322 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
Erik Språng242e22b2015-05-11 10:17:43 +0200323 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200324 if (csrc_cnames_.size() >= kRtpCsrcSize)
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000325 return -1;
Erik Språng0ea42d32015-06-25 14:46:16 +0200326
327 csrc_cnames_[SSRC] = c_name;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000328 return 0;
329}
330
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000331int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
Erik Språng242e22b2015-05-11 10:17:43 +0200332 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200333 auto it = csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000334
Erik Språng242e22b2015-05-11 10:17:43 +0200335 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000336 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200337
Erik Språng242e22b2015-05-11 10:17:43 +0200338 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000339 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000340}
341
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000342bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
danilchap162abd32015-12-10 02:39:40 -0800343 /*
344 For audio we use a fix 5 sec interval
niklase@google.com470e71d2011-07-07 08:21:25 +0000345
danilchap162abd32015-12-10 02:39:40 -0800346 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
347 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
348 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000349
350
danilchap162abd32015-12-10 02:39:40 -0800351 From RFC 3550
niklase@google.com470e71d2011-07-07 08:21:25 +0000352
danilchap162abd32015-12-10 02:39:40 -0800353 MAX RTCP BW is 5% if the session BW
354 A send report is approximately 65 bytes inc CNAME
355 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000356
danilchap162abd32015-12-10 02:39:40 -0800357 The RECOMMENDED value for the reduced minimum in seconds is 360
358 divided by the session bandwidth in kilobits/second. This minimum
359 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
niklase@google.com470e71d2011-07-07 08:21:25 +0000360
danilchap162abd32015-12-10 02:39:40 -0800361 If the participant has not yet sent an RTCP packet (the variable
362 initial is true), the constant Tmin is set to 2.5 seconds, else it
363 is set to 5 seconds.
niklase@google.com470e71d2011-07-07 08:21:25 +0000364
danilchap162abd32015-12-10 02:39:40 -0800365 The interval between RTCP packets is varied randomly over the
366 range [0.5,1.5] times the calculated interval to avoid unintended
367 synchronization of all participants
niklase@google.com470e71d2011-07-07 08:21:25 +0000368
danilchap162abd32015-12-10 02:39:40 -0800369 if we send
370 If the participant is a sender (we_sent true), the constant C is
371 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
372 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
373 number of senders.
niklase@google.com470e71d2011-07-07 08:21:25 +0000374
danilchap162abd32015-12-10 02:39:40 -0800375 if we receive only
376 If we_sent is not true, the constant C is set
377 to the average RTCP packet size divided by 75% of the RTCP
378 bandwidth. The constant n is set to the number of receivers
379 (members - senders). If the number of senders is greater than
380 25%, senders and receivers are treated together.
niklase@google.com470e71d2011-07-07 08:21:25 +0000381
danilchap162abd32015-12-10 02:39:40 -0800382 reconsideration NOT required for peer-to-peer
383 "timer reconsideration" is
384 employed. This algorithm implements a simple back-off mechanism
385 which causes users to hold back RTCP packet transmission if the
386 group sizes are increasing.
niklase@google.com470e71d2011-07-07 08:21:25 +0000387
danilchap162abd32015-12-10 02:39:40 -0800388 n = number of members
389 C = avg_size/(rtcpBW/4)
niklase@google.com470e71d2011-07-07 08:21:25 +0000390
danilchap162abd32015-12-10 02:39:40 -0800391 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
niklase@google.com470e71d2011-07-07 08:21:25 +0000392
danilchap162abd32015-12-10 02:39:40 -0800393 4. The calculated interval T is set to a number uniformly distributed
394 between 0.5 and 1.5 times the deterministic calculated interval.
niklase@google.com470e71d2011-07-07 08:21:25 +0000395
danilchap162abd32015-12-10 02:39:40 -0800396 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
397 for the fact that the timer reconsideration algorithm converges to
398 a value of the RTCP bandwidth below the intended average
399 */
niklase@google.com470e71d2011-07-07 08:21:25 +0000400
Erik Språng242e22b2015-05-11 10:17:43 +0200401 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000402
Erik Språng242e22b2015-05-11 10:17:43 +0200403 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
xians@webrtc.org8738d272011-11-25 13:43:53 +0000404
pbosda903ea2015-10-02 02:36:56 -0700405 if (method_ == RtcpMode::kOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000406 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000407
Erik Språng242e22b2015-05-11 10:17:43 +0200408 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200409 // for video key-frames we want to send the RTCP before the large key-frame
410 // if we have a 100 ms margin
411 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
412 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000413
Erik Språng242e22b2015-05-11 10:17:43 +0200414 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200415 return true;
416 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200417 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200418 // wrap
419 return true;
420 }
421 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000422}
423
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000424int64_t RTCPSender::SendTimeOfSendReport(uint32_t sendReport) {
Erik Språng242e22b2015-05-11 10:17:43 +0200425 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000426
Erik Språng61be2a42015-04-27 13:32:52 +0200427 // This is only saved when we are the sender
Erik Språng242e22b2015-05-11 10:17:43 +0200428 if ((last_send_report_[0] == 0) || (sendReport == 0)) {
Erik Språng61be2a42015-04-27 13:32:52 +0200429 return 0; // will be ignored
430 } else {
431 for (int i = 0; i < RTCP_NUMBER_OF_SR; ++i) {
Erik Språng242e22b2015-05-11 10:17:43 +0200432 if (last_send_report_[i] == sendReport)
433 return last_rtcp_time_[i];
niklase@google.com470e71d2011-07-07 08:21:25 +0000434 }
Erik Språng61be2a42015-04-27 13:32:52 +0200435 }
436 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000437}
438
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000439bool RTCPSender::SendTimeOfXrRrReport(uint32_t mid_ntp,
440 int64_t* time_ms) const {
Erik Språng242e22b2015-05-11 10:17:43 +0200441 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000442
443 if (last_xr_rr_.empty()) {
444 return false;
445 }
446 std::map<uint32_t, int64_t>::const_iterator it = last_xr_rr_.find(mid_ntp);
447 if (it == last_xr_rr_.end()) {
448 return false;
449 }
450 *time_ms = it->second;
451 return true;
452}
453
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200454int32_t RTCPSender::AddReportBlock(const RTCPReportBlock& report_block) {
455 if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000456 LOG(LS_WARNING) << "Too many report blocks.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000457 return -1;
458 }
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200459 rtcp::ReportBlock* block = &report_blocks_[report_block.remoteSSRC];
460 block->To(report_block.remoteSSRC);
461 block->WithFractionLost(report_block.fractionLost);
danilchapdf948f02015-11-13 03:03:13 -0800462 if (!block->WithCumulativeLost(report_block.cumulativeLost)) {
463 LOG(LS_WARNING) << "Cumulative lost is oversized.";
464 return -1;
465 }
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200466 block->WithExtHighestSeqNum(report_block.extendedHighSeqNum);
467 block->WithJitter(report_block.jitter);
468 block->WithLastSr(report_block.lastSR);
469 block->WithDelayLastSr(report_block.delaySinceLastSR);
470
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000471 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000472}
473
Erik Språngf7c57762015-12-04 10:40:35 +0100474rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildSR(const RtcpContext& ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200475 for (int i = (RTCP_NUMBER_OF_SR - 2); i >= 0; i--) {
476 // shift old
Erik Språng242e22b2015-05-11 10:17:43 +0200477 last_send_report_[i + 1] = last_send_report_[i];
478 last_rtcp_time_[i + 1] = last_rtcp_time_[i];
Erik Språng61be2a42015-04-27 13:32:52 +0200479 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000480
Erik Språngf7c57762015-12-04 10:40:35 +0100481 last_rtcp_time_[0] = Clock::NtpToMs(ctx.ntp_sec_, ctx.ntp_frac_);
482 last_send_report_[0] = (ctx.ntp_sec_ << 16) + (ctx.ntp_frac_ >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000483
Erik Språng61be2a42015-04-27 13:32:52 +0200484 // The timestamp of this RTCP packet should be estimated as the timestamp of
485 // the frame being captured at this moment. We are calculating that
486 // timestamp as the last frame's timestamp + the time since the last frame
487 // was captured.
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200488 uint32_t rtp_timestamp =
489 start_timestamp_ + last_rtp_timestamp_ +
490 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) *
Erik Språngf7c57762015-12-04 10:40:35 +0100491 (ctx.feedback_state_.frequency_hz / 1000);
niklase@google.com470e71d2011-07-07 08:21:25 +0000492
Erik Språngf7c57762015-12-04 10:40:35 +0100493 rtcp::SenderReport* report = new rtcp::SenderReport();
494 report->From(ssrc_);
495 report->WithNtpSec(ctx.ntp_sec_);
496 report->WithNtpFrac(ctx.ntp_frac_);
497 report->WithRtpTimestamp(rtp_timestamp);
498 report->WithPacketCount(ctx.feedback_state_.packets_sent);
499 report->WithOctetCount(ctx.feedback_state_.media_bytes_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000500
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200501 for (auto it : report_blocks_)
Erik Språngf7c57762015-12-04 10:40:35 +0100502 report->WithReportBlock(it.second);
niklase@google.com470e71d2011-07-07 08:21:25 +0000503
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200504 report_blocks_.clear();
Erik Språngf7c57762015-12-04 10:40:35 +0100505
506 return rtc::scoped_ptr<rtcp::SenderReport>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000507}
508
Erik Språngf7c57762015-12-04 10:40:35 +0100509rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildSDES(
510 const RtcpContext& ctx) {
Erik Språng0ea42d32015-06-25 14:46:16 +0200511 size_t length_cname = cname_.length();
henrikg91d6ede2015-09-17 00:24:34 -0700512 RTC_CHECK_LT(length_cname, static_cast<size_t>(RTCP_CNAME_SIZE));
niklase@google.com470e71d2011-07-07 08:21:25 +0000513
Erik Språngf7c57762015-12-04 10:40:35 +0100514 rtcp::Sdes* sdes = new rtcp::Sdes();
515 sdes->WithCName(ssrc_, cname_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200516
517 for (const auto it : csrc_cnames_)
Erik Språngf7c57762015-12-04 10:40:35 +0100518 sdes->WithCName(it.first, it.second);
Erik Språng0ea42d32015-06-25 14:46:16 +0200519
Erik Språngf7c57762015-12-04 10:40:35 +0100520 return rtc::scoped_ptr<rtcp::Sdes>(sdes);
niklase@google.com470e71d2011-07-07 08:21:25 +0000521}
522
Erik Språngf7c57762015-12-04 10:40:35 +0100523rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildRR(const RtcpContext& ctx) {
524 rtcp::ReceiverReport* report = new rtcp::ReceiverReport();
525 report->From(ssrc_);
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200526 for (auto it : report_blocks_)
Erik Språngf7c57762015-12-04 10:40:35 +0100527 report->WithReportBlock(it.second);
Erik Språng61be2a42015-04-27 13:32:52 +0200528
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200529 report_blocks_.clear();
Erik Språngf7c57762015-12-04 10:40:35 +0100530 return rtc::scoped_ptr<rtcp::ReceiverReport>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000531}
532
Erik Språngf7c57762015-12-04 10:40:35 +0100533rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildPLI(const RtcpContext& ctx) {
534 rtcp::Pli* pli = new rtcp::Pli();
535 pli->From(ssrc_);
536 pli->To(remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200537
Erik Språng242e22b2015-05-11 10:17:43 +0200538 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
539 "RTCPSender::PLI");
540 ++packet_type_counter_.pli_packets;
541 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
542 ssrc_, packet_type_counter_.pli_packets);
543
Erik Språngf7c57762015-12-04 10:40:35 +0100544 return rtc::scoped_ptr<rtcp::Pli>(pli);
Erik Språng61be2a42015-04-27 13:32:52 +0200545}
546
Erik Språngf7c57762015-12-04 10:40:35 +0100547rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildFIR(const RtcpContext& ctx) {
548 if (!ctx.repeat_)
sprang62dae192015-08-05 02:35:35 -0700549 ++sequence_number_fir_; // Do not increase if repetition.
niklase@google.com470e71d2011-07-07 08:21:25 +0000550
Erik Språngf7c57762015-12-04 10:40:35 +0100551 rtcp::Fir* fir = new rtcp::Fir();
552 fir->From(ssrc_);
553 fir->To(remote_ssrc_);
554 fir->WithCommandSeqNum(sequence_number_fir_);
Erik Språng242e22b2015-05-11 10:17:43 +0200555
556 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
557 "RTCPSender::FIR");
558 ++packet_type_counter_.fir_packets;
559 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
560 ssrc_, packet_type_counter_.fir_packets);
561
Erik Språngf7c57762015-12-04 10:40:35 +0100562 return rtc::scoped_ptr<rtcp::Fir>(fir);
niklase@google.com470e71d2011-07-07 08:21:25 +0000563}
564
565/*
566 0 1 2 3
567 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
568 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
569 | First | Number | PictureID |
570 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
571*/
Erik Språngf7c57762015-12-04 10:40:35 +0100572rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildSLI(const RtcpContext& ctx) {
573 rtcp::Sli* sli = new rtcp::Sli();
574 sli->From(ssrc_);
575 sli->To(remote_ssrc_);
sprang0365a272015-08-11 01:02:37 -0700576 // Crop picture id to 6 least significant bits.
Erik Språngf7c57762015-12-04 10:40:35 +0100577 sli->WithPictureId(ctx.picture_id_ & 0x3F);
578 sli->WithFirstMb(0);
579 sli->WithNumberOfMb(0x1FFF); // 13 bits, only ones for now.
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 =
Erik Språngf7c57762015-12-04 10:40:35 +0100647 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_);
681 tmmbr->To(remote_ssrc_);
682 tmmbr->WithBitrateKbps(tmmbr_send_);
683 tmmbr->WithOverhead(packet_oh_send_);
684
685 return rtc::scoped_ptr<rtcp::Tmmbr>(tmmbr);
Erik Språng61be2a42015-04-27 13:32:52 +0200686}
687
Erik Språngf7c57762015-12-04 10:40:35 +0100688rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBN(
689 const RtcpContext& ctx) {
Erik Språng242e22b2015-05-11 10:17:43 +0200690 TMMBRSet* boundingSet = tmmbr_help_.BoundingSetToSend();
Erik Språngf7c57762015-12-04 10:40:35 +0100691 if (boundingSet == nullptr)
692 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200693
Erik Språngf7c57762015-12-04 10:40:35 +0100694 rtcp::Tmmbn* tmmbn = new rtcp::Tmmbn();
695 tmmbn->From(ssrc_);
sprangd83df502015-08-27 01:05:08 -0700696 for (uint32_t i = 0; i < boundingSet->lengthOfSet(); i++) {
697 if (boundingSet->Tmmbr(i) > 0) {
Erik Språngf7c57762015-12-04 10:40:35 +0100698 tmmbn->WithTmmbr(boundingSet->Ssrc(i), boundingSet->Tmmbr(i),
699 boundingSet->PacketOH(i));
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000700 }
Erik Språng61be2a42015-04-27 13:32:52 +0200701 }
sprangd83df502015-08-27 01:05:08 -0700702
Erik Språngf7c57762015-12-04 10:40:35 +0100703 return rtc::scoped_ptr<rtcp::Tmmbn>(tmmbn);
niklase@google.com470e71d2011-07-07 08:21:25 +0000704}
705
Erik Språngf7c57762015-12-04 10:40:35 +0100706rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildAPP(const RtcpContext& ctx) {
707 rtcp::App* app = new rtcp::App();
708 app->From(ssrc_);
709 app->WithSubType(app_sub_type_);
710 app->WithName(app_name_);
711 app->WithData(app_data_.get(), app_length_);
Erik Språng521875a2015-09-01 10:11:16 +0200712
Erik Språngf7c57762015-12-04 10:40:35 +0100713 return rtc::scoped_ptr<rtcp::App>(app);
Erik Språng61be2a42015-04-27 13:32:52 +0200714}
715
Erik Språngf7c57762015-12-04 10:40:35 +0100716rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildNACK(
717 const RtcpContext& ctx) {
718 rtcp::Nack* nack = new rtcp::Nack();
719 nack->From(ssrc_);
720 nack->To(remote_ssrc_);
721 nack->WithList(ctx.nack_list_, ctx.nack_size_);
Erik Språng61be2a42015-04-27 13:32:52 +0200722
723 // Report stats.
724 NACKStringBuilder stringBuilder;
Erik Språngf7c57762015-12-04 10:40:35 +0100725 for (int idx = 0; idx < ctx.nack_size_; ++idx) {
726 stringBuilder.PushNACK(ctx.nack_list_[idx]);
727 nack_stats_.ReportRequest(ctx.nack_list_[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +0200728 }
Erik Språng61be2a42015-04-27 13:32:52 +0200729 packet_type_counter_.nack_requests = nack_stats_.requests();
730 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +0200731
732 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
733 "RTCPSender::NACK", "nacks",
734 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
735 ++packet_type_counter_.nack_packets;
736 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
737 ssrc_, packet_type_counter_.nack_packets);
738
Erik Språngf7c57762015-12-04 10:40:35 +0100739 return rtc::scoped_ptr<rtcp::Nack>(nack);
Erik Språng61be2a42015-04-27 13:32:52 +0200740}
741
Erik Språngf7c57762015-12-04 10:40:35 +0100742rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildBYE(const RtcpContext& ctx) {
743 rtcp::Bye* bye = new rtcp::Bye();
744 bye->From(ssrc_);
sprangd8ee4f92015-08-24 03:25:19 -0700745 for (uint32_t csrc : csrcs_)
Erik Språngf7c57762015-12-04 10:40:35 +0100746 bye->WithCsrc(csrc);
sprangd8ee4f92015-08-24 03:25:19 -0700747
Erik Språngf7c57762015-12-04 10:40:35 +0100748 return rtc::scoped_ptr<rtcp::Bye>(bye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000749}
750
Erik Språngf7c57762015-12-04 10:40:35 +0100751rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildReceiverReferenceTime(
752 const RtcpContext& ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200753 if (last_xr_rr_.size() >= RTCP_NUMBER_OF_SR)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000754 last_xr_rr_.erase(last_xr_rr_.begin());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000755 last_xr_rr_.insert(std::pair<uint32_t, int64_t>(
Erik Språngf7c57762015-12-04 10:40:35 +0100756 RTCPUtility::MidNtp(ctx.ntp_sec_, ctx.ntp_frac_),
757 Clock::NtpToMs(ctx.ntp_sec_, ctx.ntp_frac_)));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000758
Erik Språngf7c57762015-12-04 10:40:35 +0100759 rtcp::Xr* xr = new rtcp::Xr();
760 xr->From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000761
Erik Språngca28fdc2015-08-31 14:00:50 +0200762 rtcp::Rrtr rrtr;
Danil Chapovalovfc47ed62015-12-07 14:46:35 +0100763 rrtr.WithNtp(NtpTime(ctx.ntp_sec_, ctx.ntp_frac_));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000764
Erik Språngf7c57762015-12-04 10:40:35 +0100765 xr->WithRrtr(&rrtr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000766
Erik Språngca28fdc2015-08-31 14:00:50 +0200767 // TODO(sprang): Merge XR report sending to contain all of RRTR, DLRR, VOIP?
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000768
Erik Språngf7c57762015-12-04 10:40:35 +0100769 return rtc::scoped_ptr<rtcp::Xr>(xr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000770}
771
Erik Språngf7c57762015-12-04 10:40:35 +0100772rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildDlrr(
773 const RtcpContext& ctx) {
774 rtcp::Xr* xr = new rtcp::Xr();
775 xr->From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000776
Erik Språngca28fdc2015-08-31 14:00:50 +0200777 rtcp::Dlrr dlrr;
Erik Språngf7c57762015-12-04 10:40:35 +0100778 const RtcpReceiveTimeInfo& info = ctx.feedback_state_.last_xr_rr;
Erik Språngca28fdc2015-08-31 14:00:50 +0200779 dlrr.WithDlrrItem(info.sourceSSRC, info.lastRR, info.delaySinceLastRR);
780
Erik Språngf7c57762015-12-04 10:40:35 +0100781 xr->WithDlrr(&dlrr);
Erik Språngca28fdc2015-08-31 14:00:50 +0200782
Erik Språngf7c57762015-12-04 10:40:35 +0100783 return rtc::scoped_ptr<rtcp::Xr>(xr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000784}
785
Erik Språng242e22b2015-05-11 10:17:43 +0200786// TODO(sprang): Add a unit test for this, or remove if the code isn't used.
Erik Språngf7c57762015-12-04 10:40:35 +0100787rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildVoIPMetric(
788 const RtcpContext& context) {
789 rtcp::Xr* xr = new rtcp::Xr();
790 xr->From(ssrc_);
Erik Språngca28fdc2015-08-31 14:00:50 +0200791
792 rtcp::VoipMetric voip;
793 voip.To(remote_ssrc_);
794 voip.LossRate(xr_voip_metric_.lossRate);
795 voip.DiscardRate(xr_voip_metric_.discardRate);
796 voip.BurstDensity(xr_voip_metric_.burstDensity);
797 voip.GapDensity(xr_voip_metric_.gapDensity);
798 voip.BurstDuration(xr_voip_metric_.burstDuration);
799 voip.GapDuration(xr_voip_metric_.gapDuration);
800 voip.RoundTripDelay(xr_voip_metric_.roundTripDelay);
801 voip.EndSystemDelay(xr_voip_metric_.endSystemDelay);
802 voip.SignalLevel(xr_voip_metric_.signalLevel);
803 voip.NoiseLevel(xr_voip_metric_.noiseLevel);
804 voip.Rerl(xr_voip_metric_.RERL);
805 voip.Gmin(xr_voip_metric_.Gmin);
806 voip.Rfactor(xr_voip_metric_.Rfactor);
807 voip.ExtRfactor(xr_voip_metric_.extRfactor);
808 voip.MosLq(xr_voip_metric_.MOSLQ);
809 voip.MosCq(xr_voip_metric_.MOSCQ);
810 voip.RxConfig(xr_voip_metric_.RXconfig);
811 voip.JbNominal(xr_voip_metric_.JBnominal);
812 voip.JbMax(xr_voip_metric_.JBmax);
813 voip.JbAbsMax(xr_voip_metric_.JBabsMax);
814
Erik Språngf7c57762015-12-04 10:40:35 +0100815 xr->WithVoipMetric(&voip);
Erik Språngca28fdc2015-08-31 14:00:50 +0200816
Erik Språngf7c57762015-12-04 10:40:35 +0100817 return rtc::scoped_ptr<rtcp::Xr>(xr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000818}
819
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000820int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200821 RTCPPacketType packetType,
822 int32_t nack_size,
823 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000824 bool repeat,
825 uint64_t pictureID) {
Erik Språng242e22b2015-05-11 10:17:43 +0200826 return SendCompoundRTCP(
827 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
828 nack_size, nack_list, repeat, pictureID);
829}
830
831int32_t RTCPSender::SendCompoundRTCP(
832 const FeedbackState& feedback_state,
Erik Språngf7c57762015-12-04 10:40:35 +0100833 const std::set<RTCPPacketType>& packet_types,
Erik Språng242e22b2015-05-11 10:17:43 +0200834 int32_t nack_size,
835 const uint16_t* nack_list,
836 bool repeat,
837 uint64_t pictureID) {
Erik Språngf7c57762015-12-04 10:40:35 +0100838 PacketContainer container(transport_);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000839 {
Erik Språng242e22b2015-05-11 10:17:43 +0200840 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
pbosda903ea2015-10-02 02:36:56 -0700841 if (method_ == RtcpMode::kOff) {
Erik Språng61be2a42015-04-27 13:32:52 +0200842 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
843 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +0000844 }
Erik Språngf7c57762015-12-04 10:40:35 +0100845
846 // We need to send our NTP even if we haven't received any reports.
847 uint32_t ntp_sec;
848 uint32_t ntp_frac;
849 clock_->CurrentNtp(ntp_sec, ntp_frac);
850 RtcpContext context(feedback_state, nack_size, nack_list, repeat, pictureID,
851 ntp_sec, ntp_frac, &container);
852
853 PrepareReport(packet_types, feedback_state);
854
855 auto it = report_flags_.begin();
856 while (it != report_flags_.end()) {
857 auto builder_it = builders_.find(it->type);
858 RTC_DCHECK(builder_it != builders_.end());
859 if (it->is_volatile) {
860 report_flags_.erase(it++);
861 } else {
862 ++it;
863 }
864
865 BuilderFunc func = builder_it->second;
866 rtc::scoped_ptr<rtcp::RtcpPacket> packet = (this->*func)(context);
867 if (packet.get() == nullptr)
868 return -1;
869 container.Append(packet.release());
870 }
871
872 if (packet_type_counter_observer_ != nullptr) {
873 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
874 remote_ssrc_, packet_type_counter_);
875 }
876
877 RTC_DCHECK(AllVolatileFlagsConsumed());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000878 }
Erik Språng61be2a42015-04-27 13:32:52 +0200879
Erik Språngf7c57762015-12-04 10:40:35 +0100880 size_t bytes_sent = container.SendPackets();
881 return bytes_sent == 0 ? -1 : 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000882}
883
Erik Språngf7c57762015-12-04 10:40:35 +0100884void RTCPSender::PrepareReport(const std::set<RTCPPacketType>& packetTypes,
885 const FeedbackState& feedback_state) {
Erik Språng242e22b2015-05-11 10:17:43 +0200886 // Add all flags as volatile. Non volatile entries will not be overwritten
887 // and all new volatile flags added will be consumed by the end of this call.
888 SetFlags(packetTypes, true);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000889
Erik Språng61be2a42015-04-27 13:32:52 +0200890 if (packet_type_counter_.first_packet_time_ms == -1)
Erik Språng242e22b2015-05-11 10:17:43 +0200891 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språng61be2a42015-04-27 13:32:52 +0200892
Erik Språng242e22b2015-05-11 10:17:43 +0200893 bool generate_report;
894 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
895 // Report type already explicitly set, don't automatically populate.
896 generate_report = true;
henrikg91d6ede2015-09-17 00:24:34 -0700897 RTC_DCHECK(ConsumeFlag(kRtcpReport) == false);
Erik Språng242e22b2015-05-11 10:17:43 +0200898 } else {
899 generate_report =
pbosda903ea2015-10-02 02:36:56 -0700900 (ConsumeFlag(kRtcpReport) && method_ == RtcpMode::kReducedSize) ||
901 method_ == RtcpMode::kCompound;
Erik Språng242e22b2015-05-11 10:17:43 +0200902 if (generate_report)
903 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000904 }
905
Erik Språng0ea42d32015-06-25 14:46:16 +0200906 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
Erik Språng242e22b2015-05-11 10:17:43 +0200907 SetFlag(kRtcpSdes, true);
908
Erik Språng242e22b2015-05-11 10:17:43 +0200909 if (generate_report) {
910 if (!sending_ && xr_send_receiver_reference_time_enabled_)
911 SetFlag(kRtcpXrReceiverReferenceTime, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200912 if (feedback_state.has_last_xr_rr)
Erik Språng242e22b2015-05-11 10:17:43 +0200913 SetFlag(kRtcpXrDlrrReportBlock, true);
914
915 // generate next time to send an RTCP report
Erik Språng61be2a42015-04-27 13:32:52 +0200916 // seeded from RTP constructor
917 int32_t random = rand() % 1000;
918 int32_t timeToNext = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000919
Erik Språng242e22b2015-05-11 10:17:43 +0200920 if (audio_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200921 timeToNext = (RTCP_INTERVAL_AUDIO_MS / 2) +
922 (RTCP_INTERVAL_AUDIO_MS * random / 1000);
923 } else {
924 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
Erik Språng242e22b2015-05-11 10:17:43 +0200925 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200926 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
927 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
928 if (send_bitrate_kbit != 0)
929 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000930 }
Erik Språng61be2a42015-04-27 13:32:52 +0200931 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
932 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
933 timeToNext = (minIntervalMs / 2) + (minIntervalMs * random / 1000);
934 }
Erik Språng242e22b2015-05-11 10:17:43 +0200935 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000936
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000937 StatisticianMap statisticians =
938 receive_statistics_->GetActiveStatisticians();
939 if (!statisticians.empty()) {
Erik Språng61be2a42015-04-27 13:32:52 +0200940 for (auto it = statisticians.begin(); it != statisticians.end(); ++it) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000941 RTCPReportBlock report_block;
Erik Språngf7c57762015-12-04 10:40:35 +0100942 if (PrepareReportBlock(feedback_state, it->first, it->second,
943 &report_block)) {
danilchapdf948f02015-11-13 03:03:13 -0800944 // TODO(danilchap) AddReportBlock may fail (for 2 different reasons).
945 // Probably it shouldn't be ignored.
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200946 AddReportBlock(report_block);
Erik Språng61be2a42015-04-27 13:32:52 +0200947 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000948 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000949 }
950 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000951}
952
Erik Språngf7c57762015-12-04 10:40:35 +0100953bool RTCPSender::PrepareReportBlock(const FeedbackState& feedback_state,
954 uint32_t ssrc,
955 StreamStatistician* statistician,
956 RTCPReportBlock* report_block) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000957 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000958 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000959 if (!statistician->GetStatistics(&stats, true))
960 return false;
961 report_block->fractionLost = stats.fraction_lost;
962 report_block->cumulativeLost = stats.cumulative_lost;
danilchap162abd32015-12-10 02:39:40 -0800963 report_block->extendedHighSeqNum = stats.extended_max_sequence_number;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000964 report_block->jitter = stats.jitter;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200965 report_block->remoteSSRC = ssrc;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000966
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200967 // TODO(sprang): Do we really need separate time stamps for each report?
968 // Get our NTP as late as possible to avoid a race.
969 uint32_t ntp_secs;
970 uint32_t ntp_frac;
971 clock_->CurrentNtp(ntp_secs, ntp_frac);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000972
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200973 // Delay since last received report.
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000974 uint32_t delaySinceLastReceivedSR = 0;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000975 if ((feedback_state.last_rr_ntp_secs != 0) ||
976 (feedback_state.last_rr_ntp_frac != 0)) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200977 // Get the 16 lowest bits of seconds and the 16 highest bits of fractions.
978 uint32_t now = ntp_secs & 0x0000FFFF;
Erik Språng61be2a42015-04-27 13:32:52 +0200979 now <<= 16;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200980 now += (ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000981
Erik Språng61be2a42015-04-27 13:32:52 +0200982 uint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
983 receiveTime <<= 16;
984 receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000985
danilchap162abd32015-12-10 02:39:40 -0800986 delaySinceLastReceivedSR = now - receiveTime;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000987 }
988 report_block->delaySinceLastSR = delaySinceLastReceivedSR;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000989 report_block->lastSR = feedback_state.remote_sr;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000990 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000991}
992
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000993void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
994 assert(csrcs.size() <= kRtpCsrcSize);
Erik Språng242e22b2015-05-11 10:17:43 +0200995 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000996 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +0000997}
998
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000999int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
1000 uint32_t name,
1001 const uint8_t* data,
1002 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +02001003 if (length % 4 != 0) {
1004 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
1005 return -1;
1006 }
Erik Språng242e22b2015-05-11 10:17:43 +02001007 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +00001008
Erik Språng242e22b2015-05-11 10:17:43 +02001009 SetFlag(kRtcpApp, true);
1010 app_sub_type_ = subType;
1011 app_name_ = name;
1012 app_data_.reset(new uint8_t[length]);
1013 app_length_ = length;
1014 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +02001015 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001016}
1017
Erik Språng61be2a42015-04-27 13:32:52 +02001018int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
Erik Språng242e22b2015-05-11 10:17:43 +02001019 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1020 memcpy(&xr_voip_metric_, VoIPMetric, sizeof(RTCPVoIPMetric));
niklase@google.com470e71d2011-07-07 08:21:25 +00001021
Erik Språng242e22b2015-05-11 10:17:43 +02001022 SetFlag(kRtcpXrVoipMetric, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001023 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001024}
1025
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001026void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +02001027 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1028 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001029}
1030
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00001031bool RTCPSender::RtcpXrReceiverReferenceTime() const {
Erik Språng242e22b2015-05-11 10:17:43 +02001032 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1033 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00001034}
1035
niklase@google.com470e71d2011-07-07 08:21:25 +00001036// no callbacks allowed inside this function
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001037int32_t RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
1038 uint32_t maxBitrateKbit) {
Erik Språng242e22b2015-05-11 10:17:43 +02001039 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +00001040
Erik Språng242e22b2015-05-11 10:17:43 +02001041 if (0 == tmmbr_help_.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit)) {
1042 SetFlag(kRtcpTmmbn, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001043 return 0;
1044 }
1045 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001046}
Erik Språng61be2a42015-04-27 13:32:52 +02001047
Erik Språng242e22b2015-05-11 10:17:43 +02001048void RTCPSender::SetFlag(RTCPPacketType type, bool is_volatile) {
1049 report_flags_.insert(ReportFlag(type, is_volatile));
1050}
1051
1052void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
1053 bool is_volatile) {
1054 for (RTCPPacketType type : types)
1055 SetFlag(type, is_volatile);
1056}
1057
1058bool RTCPSender::IsFlagPresent(RTCPPacketType type) const {
1059 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
1060}
1061
1062bool RTCPSender::ConsumeFlag(RTCPPacketType type, bool forced) {
1063 auto it = report_flags_.find(ReportFlag(type, false));
1064 if (it == report_flags_.end())
1065 return false;
1066 if (it->is_volatile || forced)
1067 report_flags_.erase((it));
1068 return true;
1069}
1070
1071bool RTCPSender::AllVolatileFlagsConsumed() const {
1072 for (const ReportFlag& flag : report_flags_) {
1073 if (flag.is_volatile)
1074 return false;
1075 }
1076 return true;
1077}
1078
sprang233bd872015-09-08 13:25:16 -07001079bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
sprang233bd872015-09-08 13:25:16 -07001080 class Sender : public rtcp::RtcpPacket::PacketReadyCallback {
1081 public:
Peter Boströmac547a62015-09-17 23:03:57 +02001082 Sender(Transport* transport)
1083 : transport_(transport), send_failure_(false) {}
sprang233bd872015-09-08 13:25:16 -07001084
1085 void OnPacketReady(uint8_t* data, size_t length) override {
pbos2d566682015-09-28 09:59:31 -07001086 if (!transport_->SendRtcp(data, length))
sprang233bd872015-09-08 13:25:16 -07001087 send_failure_ = true;
1088 }
1089
1090 Transport* const transport_;
sprang233bd872015-09-08 13:25:16 -07001091 bool send_failure_;
sprang86fd9ed2015-09-29 04:45:43 -07001092 } sender(transport_);
sprang233bd872015-09-08 13:25:16 -07001093
1094 uint8_t buffer[IP_PACKET_SIZE];
1095 return packet.BuildExternalBuffer(buffer, IP_PACKET_SIZE, &sender) &&
1096 !sender.send_failure_;
1097}
1098
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001099} // namespace webrtc