blob: 15f9388b578983b27368b7ad2ddfb6883377d0f1 [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"
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),
danilchap47a740b2015-12-15 00:30:07 -0800143 random_(clock_->TimeInMicroseconds()),
pbosda903ea2015-10-02 02:36:56 -0700144 method_(RtcpMode::kOff),
sprang86fd9ed2015-09-29 04:45:43 -0700145 transport_(outgoing_transport),
niklase@google.com470e71d2011-07-07 08:21:25 +0000146
Erik Språng242e22b2015-05-11 10:17:43 +0200147 critical_section_rtcp_sender_(
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000148 CriticalSectionWrapper::CreateCriticalSection()),
Erik Språng242e22b2015-05-11 10:17:43 +0200149 using_nack_(false),
150 sending_(false),
151 remb_enabled_(false),
Erik Språng242e22b2015-05-11 10:17:43 +0200152 next_time_to_send_rtcp_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000153 start_timestamp_(0),
154 last_rtp_timestamp_(0),
155 last_frame_capture_time_ms_(-1),
Erik Språng242e22b2015-05-11 10:17:43 +0200156 ssrc_(0),
157 remote_ssrc_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000158 receive_statistics_(receive_statistics),
niklase@google.com470e71d2011-07-07 08:21:25 +0000159
Erik Språng242e22b2015-05-11 10:17:43 +0200160 sequence_number_fir_(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000161
Erik Språng242e22b2015-05-11 10:17:43 +0200162 remb_bitrate_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000163
Erik Språng242e22b2015-05-11 10:17:43 +0200164 tmmbr_help_(),
165 tmmbr_send_(0),
166 packet_oh_send_(0),
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000167
Erik Språng242e22b2015-05-11 10:17:43 +0200168 app_sub_type_(0),
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200169 app_name_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200170 app_data_(nullptr),
171 app_length_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000172
Erik Språng242e22b2015-05-11 10:17:43 +0200173 xr_send_receiver_reference_time_enabled_(false),
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000174 packet_type_counter_observer_(packet_type_counter_observer) {
Erik Språng242e22b2015-05-11 10:17:43 +0200175 memset(last_send_report_, 0, sizeof(last_send_report_));
176 memset(last_rtcp_time_, 0, sizeof(last_rtcp_time_));
sprang86fd9ed2015-09-29 04:45:43 -0700177 RTC_DCHECK(transport_ != nullptr);
Erik Språng242e22b2015-05-11 10:17:43 +0200178
179 builders_[kRtcpSr] = &RTCPSender::BuildSR;
180 builders_[kRtcpRr] = &RTCPSender::BuildRR;
Erik Språng0ea42d32015-06-25 14:46:16 +0200181 builders_[kRtcpSdes] = &RTCPSender::BuildSDES;
Erik Språng242e22b2015-05-11 10:17:43 +0200182 builders_[kRtcpPli] = &RTCPSender::BuildPLI;
183 builders_[kRtcpFir] = &RTCPSender::BuildFIR;
184 builders_[kRtcpSli] = &RTCPSender::BuildSLI;
185 builders_[kRtcpRpsi] = &RTCPSender::BuildRPSI;
186 builders_[kRtcpRemb] = &RTCPSender::BuildREMB;
187 builders_[kRtcpBye] = &RTCPSender::BuildBYE;
188 builders_[kRtcpApp] = &RTCPSender::BuildAPP;
189 builders_[kRtcpTmmbr] = &RTCPSender::BuildTMMBR;
190 builders_[kRtcpTmmbn] = &RTCPSender::BuildTMMBN;
191 builders_[kRtcpNack] = &RTCPSender::BuildNACK;
192 builders_[kRtcpXrVoipMetric] = &RTCPSender::BuildVoIPMetric;
193 builders_[kRtcpXrReceiverReferenceTime] =
194 &RTCPSender::BuildReceiverReferenceTime;
195 builders_[kRtcpXrDlrrReportBlock] = &RTCPSender::BuildDlrr;
niklase@google.com470e71d2011-07-07 08:21:25 +0000196}
197
danilchap162abd32015-12-10 02:39:40 -0800198RTCPSender::~RTCPSender() {}
niklase@google.com470e71d2011-07-07 08:21:25 +0000199
pbosda903ea2015-10-02 02:36:56 -0700200RtcpMode RTCPSender::Status() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200201 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
202 return method_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000203}
204
pbosda903ea2015-10-02 02:36:56 -0700205void RTCPSender::SetRTCPStatus(RtcpMode method) {
Erik Språng242e22b2015-05-11 10:17:43 +0200206 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
207 method_ = method;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000208
pbosda903ea2015-10-02 02:36:56 -0700209 if (method == RtcpMode::kOff)
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000210 return;
Erik Språng242e22b2015-05-11 10:17:43 +0200211 next_time_to_send_rtcp_ =
212 clock_->TimeInMilliseconds() +
213 (audio_ ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000214}
215
Erik Språng61be2a42015-04-27 13:32:52 +0200216bool RTCPSender::Sending() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200217 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
218 return sending_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000219}
220
Erik Språng61be2a42015-04-27 13:32:52 +0200221int32_t RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
222 bool sending) {
223 bool sendRTCPBye = false;
224 {
Erik Språng242e22b2015-05-11 10:17:43 +0200225 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000226
pbosda903ea2015-10-02 02:36:56 -0700227 if (method_ != RtcpMode::kOff) {
Erik Språng242e22b2015-05-11 10:17:43 +0200228 if (sending == false && sending_ == true) {
Erik Språng61be2a42015-04-27 13:32:52 +0200229 // Trigger RTCP bye
230 sendRTCPBye = true;
231 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000232 }
Erik Språng242e22b2015-05-11 10:17:43 +0200233 sending_ = sending;
Erik Språng61be2a42015-04-27 13:32:52 +0200234 }
235 if (sendRTCPBye)
236 return SendRTCP(feedback_state, kRtcpBye);
237 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000238}
239
Erik Språng61be2a42015-04-27 13:32:52 +0200240bool RTCPSender::REMB() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200241 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
242 return remb_enabled_;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000243}
244
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000245void RTCPSender::SetREMBStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200246 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
247 remb_enabled_ = enable;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000248}
249
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000250void RTCPSender::SetREMBData(uint32_t bitrate,
251 const std::vector<uint32_t>& ssrcs) {
Erik Språng242e22b2015-05-11 10:17:43 +0200252 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
253 remb_bitrate_ = bitrate;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000254 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000255
Erik Språng242e22b2015-05-11 10:17:43 +0200256 if (remb_enabled_)
257 SetFlag(kRtcpRemb, false);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000258 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
259 // throttled by the caller.
Erik Språng242e22b2015-05-11 10:17:43 +0200260 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000261}
262
Erik Språng61be2a42015-04-27 13:32:52 +0200263bool RTCPSender::TMMBR() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200264 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
265 return IsFlagPresent(RTCPPacketType::kRtcpTmmbr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000266}
267
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000268void RTCPSender::SetTMMBRStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200269 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
270 if (enable) {
271 SetFlag(RTCPPacketType::kRtcpTmmbr, false);
272 } else {
273 ConsumeFlag(RTCPPacketType::kRtcpTmmbr, true);
274 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000275}
276
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000277void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
Erik Språng242e22b2015-05-11 10:17:43 +0200278 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000279 start_timestamp_ = start_timestamp;
280}
281
282void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
283 int64_t capture_time_ms) {
Erik Språng242e22b2015-05-11 10:17:43 +0200284 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000285 last_rtp_timestamp_ = rtp_timestamp;
286 if (capture_time_ms < 0) {
287 // We don't currently get a capture time from VoiceEngine.
Erik Språng242e22b2015-05-11 10:17:43 +0200288 last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000289 } else {
290 last_frame_capture_time_ms_ = capture_time_ms;
291 }
292}
293
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000294void RTCPSender::SetSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200295 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000296
Erik Språng242e22b2015-05-11 10:17:43 +0200297 if (ssrc_ != 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200298 // not first SetSSRC, probably due to a collision
299 // schedule a new RTCP report
300 // make sure that we send a RTP packet
Erik Språng242e22b2015-05-11 10:17:43 +0200301 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
Erik Språng61be2a42015-04-27 13:32:52 +0200302 }
Erik Språng242e22b2015-05-11 10:17:43 +0200303 ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000304}
305
Erik Språng61be2a42015-04-27 13:32:52 +0200306void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200307 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
308 remote_ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000309}
310
Peter Boström9ba52f82015-06-01 14:12:28 +0200311int32_t RTCPSender::SetCNAME(const char* c_name) {
312 if (!c_name)
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000313 return -1;
314
henrikg91d6ede2015-09-17 00:24:34 -0700315 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
Erik Språng242e22b2015-05-11 10:17:43 +0200316 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200317 cname_ = c_name;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000318 return 0;
319}
320
Erik Språng0ea42d32015-06-25 14:46:16 +0200321int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC, const char* c_name) {
322 assert(c_name);
henrikg91d6ede2015-09-17 00:24:34 -0700323 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
Erik Språng242e22b2015-05-11 10:17:43 +0200324 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200325 if (csrc_cnames_.size() >= kRtpCsrcSize)
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000326 return -1;
Erik Språng0ea42d32015-06-25 14:46:16 +0200327
328 csrc_cnames_[SSRC] = c_name;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000329 return 0;
330}
331
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000332int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
Erik Språng242e22b2015-05-11 10:17:43 +0200333 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200334 auto it = csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000335
Erik Språng242e22b2015-05-11 10:17:43 +0200336 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000337 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200338
Erik Språng242e22b2015-05-11 10:17:43 +0200339 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000340 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000341}
342
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000343bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
danilchap162abd32015-12-10 02:39:40 -0800344 /*
345 For audio we use a fix 5 sec interval
niklase@google.com470e71d2011-07-07 08:21:25 +0000346
danilchap162abd32015-12-10 02:39:40 -0800347 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
348 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
349 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000350
351
danilchap162abd32015-12-10 02:39:40 -0800352 From RFC 3550
niklase@google.com470e71d2011-07-07 08:21:25 +0000353
danilchap162abd32015-12-10 02:39:40 -0800354 MAX RTCP BW is 5% if the session BW
355 A send report is approximately 65 bytes inc CNAME
356 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000357
danilchap162abd32015-12-10 02:39:40 -0800358 The RECOMMENDED value for the reduced minimum in seconds is 360
359 divided by the session bandwidth in kilobits/second. This minimum
360 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
niklase@google.com470e71d2011-07-07 08:21:25 +0000361
danilchap162abd32015-12-10 02:39:40 -0800362 If the participant has not yet sent an RTCP packet (the variable
363 initial is true), the constant Tmin is set to 2.5 seconds, else it
364 is set to 5 seconds.
niklase@google.com470e71d2011-07-07 08:21:25 +0000365
danilchap162abd32015-12-10 02:39:40 -0800366 The interval between RTCP packets is varied randomly over the
367 range [0.5,1.5] times the calculated interval to avoid unintended
368 synchronization of all participants
niklase@google.com470e71d2011-07-07 08:21:25 +0000369
danilchap162abd32015-12-10 02:39:40 -0800370 if we send
371 If the participant is a sender (we_sent true), the constant C is
372 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
373 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
374 number of senders.
niklase@google.com470e71d2011-07-07 08:21:25 +0000375
danilchap162abd32015-12-10 02:39:40 -0800376 if we receive only
377 If we_sent is not true, the constant C is set
378 to the average RTCP packet size divided by 75% of the RTCP
379 bandwidth. The constant n is set to the number of receivers
380 (members - senders). If the number of senders is greater than
381 25%, senders and receivers are treated together.
niklase@google.com470e71d2011-07-07 08:21:25 +0000382
danilchap162abd32015-12-10 02:39:40 -0800383 reconsideration NOT required for peer-to-peer
384 "timer reconsideration" is
385 employed. This algorithm implements a simple back-off mechanism
386 which causes users to hold back RTCP packet transmission if the
387 group sizes are increasing.
niklase@google.com470e71d2011-07-07 08:21:25 +0000388
danilchap162abd32015-12-10 02:39:40 -0800389 n = number of members
390 C = avg_size/(rtcpBW/4)
niklase@google.com470e71d2011-07-07 08:21:25 +0000391
danilchap162abd32015-12-10 02:39:40 -0800392 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
niklase@google.com470e71d2011-07-07 08:21:25 +0000393
danilchap162abd32015-12-10 02:39:40 -0800394 4. The calculated interval T is set to a number uniformly distributed
395 between 0.5 and 1.5 times the deterministic calculated interval.
niklase@google.com470e71d2011-07-07 08:21:25 +0000396
danilchap162abd32015-12-10 02:39:40 -0800397 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
398 for the fact that the timer reconsideration algorithm converges to
399 a value of the RTCP bandwidth below the intended average
400 */
niklase@google.com470e71d2011-07-07 08:21:25 +0000401
Erik Språng242e22b2015-05-11 10:17:43 +0200402 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000403
Erik Språng242e22b2015-05-11 10:17:43 +0200404 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
xians@webrtc.org8738d272011-11-25 13:43:53 +0000405
pbosda903ea2015-10-02 02:36:56 -0700406 if (method_ == RtcpMode::kOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000407 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000408
Erik Språng242e22b2015-05-11 10:17:43 +0200409 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200410 // for video key-frames we want to send the RTCP before the large key-frame
411 // if we have a 100 ms margin
412 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
413 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000414
Erik Språng242e22b2015-05-11 10:17:43 +0200415 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200416 return true;
417 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200418 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200419 // wrap
420 return true;
421 }
422 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000423}
424
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000425int64_t RTCPSender::SendTimeOfSendReport(uint32_t sendReport) {
Erik Språng242e22b2015-05-11 10:17:43 +0200426 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000427
Erik Språng61be2a42015-04-27 13:32:52 +0200428 // This is only saved when we are the sender
Erik Språng242e22b2015-05-11 10:17:43 +0200429 if ((last_send_report_[0] == 0) || (sendReport == 0)) {
Erik Språng61be2a42015-04-27 13:32:52 +0200430 return 0; // will be ignored
431 } else {
432 for (int i = 0; i < RTCP_NUMBER_OF_SR; ++i) {
Erik Språng242e22b2015-05-11 10:17:43 +0200433 if (last_send_report_[i] == sendReport)
434 return last_rtcp_time_[i];
niklase@google.com470e71d2011-07-07 08:21:25 +0000435 }
Erik Språng61be2a42015-04-27 13:32:52 +0200436 }
437 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000438}
439
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000440bool RTCPSender::SendTimeOfXrRrReport(uint32_t mid_ntp,
441 int64_t* time_ms) const {
Erik Språng242e22b2015-05-11 10:17:43 +0200442 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000443
444 if (last_xr_rr_.empty()) {
445 return false;
446 }
447 std::map<uint32_t, int64_t>::const_iterator it = last_xr_rr_.find(mid_ntp);
448 if (it == last_xr_rr_.end()) {
449 return false;
450 }
451 *time_ms = it->second;
452 return true;
453}
454
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200455int32_t RTCPSender::AddReportBlock(const RTCPReportBlock& report_block) {
456 if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000457 LOG(LS_WARNING) << "Too many report blocks.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000458 return -1;
459 }
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200460 rtcp::ReportBlock* block = &report_blocks_[report_block.remoteSSRC];
461 block->To(report_block.remoteSSRC);
462 block->WithFractionLost(report_block.fractionLost);
danilchapdf948f02015-11-13 03:03:13 -0800463 if (!block->WithCumulativeLost(report_block.cumulativeLost)) {
464 LOG(LS_WARNING) << "Cumulative lost is oversized.";
465 return -1;
466 }
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200467 block->WithExtHighestSeqNum(report_block.extendedHighSeqNum);
468 block->WithJitter(report_block.jitter);
469 block->WithLastSr(report_block.lastSR);
470 block->WithDelayLastSr(report_block.delaySinceLastSR);
471
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000472 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000473}
474
Erik Språngf7c57762015-12-04 10:40:35 +0100475rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildSR(const RtcpContext& ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200476 for (int i = (RTCP_NUMBER_OF_SR - 2); i >= 0; i--) {
477 // shift old
Erik Språng242e22b2015-05-11 10:17:43 +0200478 last_send_report_[i + 1] = last_send_report_[i];
479 last_rtcp_time_[i + 1] = last_rtcp_time_[i];
Erik Språng61be2a42015-04-27 13:32:52 +0200480 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000481
Erik Språngf7c57762015-12-04 10:40:35 +0100482 last_rtcp_time_[0] = Clock::NtpToMs(ctx.ntp_sec_, ctx.ntp_frac_);
483 last_send_report_[0] = (ctx.ntp_sec_ << 16) + (ctx.ntp_frac_ >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000484
Erik Språng61be2a42015-04-27 13:32:52 +0200485 // The timestamp of this RTCP packet should be estimated as the timestamp of
486 // the frame being captured at this moment. We are calculating that
487 // timestamp as the last frame's timestamp + the time since the last frame
488 // was captured.
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200489 uint32_t rtp_timestamp =
490 start_timestamp_ + last_rtp_timestamp_ +
491 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) *
Erik Språngf7c57762015-12-04 10:40:35 +0100492 (ctx.feedback_state_.frequency_hz / 1000);
niklase@google.com470e71d2011-07-07 08:21:25 +0000493
Erik Språngf7c57762015-12-04 10:40:35 +0100494 rtcp::SenderReport* report = new rtcp::SenderReport();
495 report->From(ssrc_);
496 report->WithNtpSec(ctx.ntp_sec_);
497 report->WithNtpFrac(ctx.ntp_frac_);
498 report->WithRtpTimestamp(rtp_timestamp);
499 report->WithPacketCount(ctx.feedback_state_.packets_sent);
500 report->WithOctetCount(ctx.feedback_state_.media_bytes_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000501
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200502 for (auto it : report_blocks_)
Erik Språngf7c57762015-12-04 10:40:35 +0100503 report->WithReportBlock(it.second);
niklase@google.com470e71d2011-07-07 08:21:25 +0000504
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200505 report_blocks_.clear();
Erik Språngf7c57762015-12-04 10:40:35 +0100506
507 return rtc::scoped_ptr<rtcp::SenderReport>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000508}
509
Erik Språngf7c57762015-12-04 10:40:35 +0100510rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildSDES(
511 const RtcpContext& ctx) {
Erik Språng0ea42d32015-06-25 14:46:16 +0200512 size_t length_cname = cname_.length();
henrikg91d6ede2015-09-17 00:24:34 -0700513 RTC_CHECK_LT(length_cname, static_cast<size_t>(RTCP_CNAME_SIZE));
niklase@google.com470e71d2011-07-07 08:21:25 +0000514
Erik Språngf7c57762015-12-04 10:40:35 +0100515 rtcp::Sdes* sdes = new rtcp::Sdes();
516 sdes->WithCName(ssrc_, cname_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200517
518 for (const auto it : csrc_cnames_)
Erik Språngf7c57762015-12-04 10:40:35 +0100519 sdes->WithCName(it.first, it.second);
Erik Språng0ea42d32015-06-25 14:46:16 +0200520
Erik Språngf7c57762015-12-04 10:40:35 +0100521 return rtc::scoped_ptr<rtcp::Sdes>(sdes);
niklase@google.com470e71d2011-07-07 08:21:25 +0000522}
523
Erik Språngf7c57762015-12-04 10:40:35 +0100524rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildRR(const RtcpContext& ctx) {
525 rtcp::ReceiverReport* report = new rtcp::ReceiverReport();
526 report->From(ssrc_);
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200527 for (auto it : report_blocks_)
Erik Språngf7c57762015-12-04 10:40:35 +0100528 report->WithReportBlock(it.second);
Erik Språng61be2a42015-04-27 13:32:52 +0200529
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200530 report_blocks_.clear();
Erik Språngf7c57762015-12-04 10:40:35 +0100531 return rtc::scoped_ptr<rtcp::ReceiverReport>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000532}
533
Erik Språngf7c57762015-12-04 10:40:35 +0100534rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildPLI(const RtcpContext& ctx) {
535 rtcp::Pli* pli = new rtcp::Pli();
536 pli->From(ssrc_);
537 pli->To(remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200538
Erik Språng242e22b2015-05-11 10:17:43 +0200539 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
540 "RTCPSender::PLI");
541 ++packet_type_counter_.pli_packets;
542 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
543 ssrc_, packet_type_counter_.pli_packets);
544
Erik Språngf7c57762015-12-04 10:40:35 +0100545 return rtc::scoped_ptr<rtcp::Pli>(pli);
Erik Språng61be2a42015-04-27 13:32:52 +0200546}
547
Erik Språngf7c57762015-12-04 10:40:35 +0100548rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildFIR(const RtcpContext& ctx) {
549 if (!ctx.repeat_)
sprang62dae192015-08-05 02:35:35 -0700550 ++sequence_number_fir_; // Do not increase if repetition.
niklase@google.com470e71d2011-07-07 08:21:25 +0000551
Erik Språngf7c57762015-12-04 10:40:35 +0100552 rtcp::Fir* fir = new rtcp::Fir();
553 fir->From(ssrc_);
554 fir->To(remote_ssrc_);
555 fir->WithCommandSeqNum(sequence_number_fir_);
Erik Språng242e22b2015-05-11 10:17:43 +0200556
557 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
558 "RTCPSender::FIR");
559 ++packet_type_counter_.fir_packets;
560 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
561 ssrc_, packet_type_counter_.fir_packets);
562
Erik Språngf7c57762015-12-04 10:40:35 +0100563 return rtc::scoped_ptr<rtcp::Fir>(fir);
niklase@google.com470e71d2011-07-07 08:21:25 +0000564}
565
566/*
567 0 1 2 3
568 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
569 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
570 | First | Number | PictureID |
571 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
572*/
Erik Språngf7c57762015-12-04 10:40:35 +0100573rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildSLI(const RtcpContext& ctx) {
574 rtcp::Sli* sli = new rtcp::Sli();
575 sli->From(ssrc_);
576 sli->To(remote_ssrc_);
sprang0365a272015-08-11 01:02:37 -0700577 // Crop picture id to 6 least significant bits.
Erik Språngf7c57762015-12-04 10:40:35 +0100578 sli->WithPictureId(ctx.picture_id_ & 0x3F);
579 sli->WithFirstMb(0);
580 sli->WithNumberOfMb(0x1FFF); // 13 bits, only ones for now.
sprang0365a272015-08-11 01:02:37 -0700581
Erik Språngf7c57762015-12-04 10:40:35 +0100582 return rtc::scoped_ptr<rtcp::Sli>(sli);
niklase@google.com470e71d2011-07-07 08:21:25 +0000583}
584
585/*
586 0 1 2 3
587 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
588 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
589 | PB |0| Payload Type| Native RPSI bit string |
590 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
591 | defined per codec ... | Padding (0) |
592 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
593*/
594/*
595* Note: not generic made for VP8
596*/
Erik Språngf7c57762015-12-04 10:40:35 +0100597rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildRPSI(
598 const RtcpContext& ctx) {
599 if (ctx.feedback_state_.send_payload_type == 0xFF)
600 return nullptr;
Erik Språng242e22b2015-05-11 10:17:43 +0200601
Erik Språngf7c57762015-12-04 10:40:35 +0100602 rtcp::Rpsi* rpsi = new rtcp::Rpsi();
603 rpsi->From(ssrc_);
604 rpsi->To(remote_ssrc_);
605 rpsi->WithPayloadType(ctx.feedback_state_.send_payload_type);
606 rpsi->WithPictureId(ctx.picture_id_);
sprangcf7f54d2015-08-13 04:37:42 -0700607
Erik Språngf7c57762015-12-04 10:40:35 +0100608 return rtc::scoped_ptr<rtcp::Rpsi>(rpsi);
niklase@google.com470e71d2011-07-07 08:21:25 +0000609}
610
Erik Språngf7c57762015-12-04 10:40:35 +0100611rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildREMB(
612 const RtcpContext& ctx) {
613 rtcp::Remb* remb = new rtcp::Remb();
614 remb->From(ssrc_);
sprangdd4edc52015-08-21 04:21:51 -0700615 for (uint32_t ssrc : remb_ssrcs_)
Erik Språngf7c57762015-12-04 10:40:35 +0100616 remb->AppliesTo(ssrc);
617 remb->WithBitrateBps(remb_bitrate_);
Erik Språng61be2a42015-04-27 13:32:52 +0200618
Erik Språng242e22b2015-05-11 10:17:43 +0200619 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
620 "RTCPSender::REMB");
621
Erik Språngf7c57762015-12-04 10:40:35 +0100622 return rtc::scoped_ptr<rtcp::Remb>(remb);
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000623}
624
Erik Språng61be2a42015-04-27 13:32:52 +0200625void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
Erik Språng242e22b2015-05-11 10:17:43 +0200626 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
627 tmmbr_send_ = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000628}
629
Erik Språngf7c57762015-12-04 10:40:35 +0100630rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBR(
631 const RtcpContext& ctx) {
632 if (ctx.feedback_state_.module == nullptr)
633 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200634 // Before sending the TMMBR check the received TMMBN, only an owner is
635 // allowed to raise the bitrate:
636 // * If the sender is an owner of the TMMBN -> send TMMBR
637 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000638
Erik Språng61be2a42015-04-27 13:32:52 +0200639 // get current bounding set from RTCP receiver
640 bool tmmbrOwner = false;
641 // store in candidateSet, allocates one extra slot
Erik Språng242e22b2015-05-11 10:17:43 +0200642 TMMBRSet* candidateSet = tmmbr_help_.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000643
Erik Språng242e22b2015-05-11 10:17:43 +0200644 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
645 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
Erik Språng61be2a42015-04-27 13:32:52 +0200646 // since RTCPreceiver is not doing the reverse we should be fine
647 int32_t lengthOfBoundingSet =
danilchap6db6cdc2015-12-15 02:54:47 -0800648 ctx.feedback_state_.module->BoundingSet(&tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +0000649
Erik Språng61be2a42015-04-27 13:32:52 +0200650 if (lengthOfBoundingSet > 0) {
651 for (int32_t i = 0; i < lengthOfBoundingSet; i++) {
Erik Språng242e22b2015-05-11 10:17:43 +0200652 if (candidateSet->Tmmbr(i) == tmmbr_send_ &&
653 candidateSet->PacketOH(i) == packet_oh_send_) {
Erik Språngf7c57762015-12-04 10:40:35 +0100654 // Do not send the same tuple.
655 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200656 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000657 }
Erik Språng61be2a42015-04-27 13:32:52 +0200658 if (!tmmbrOwner) {
659 // use received bounding set as candidate set
660 // add current tuple
Erik Språng242e22b2015-05-11 10:17:43 +0200661 candidateSet->SetEntry(lengthOfBoundingSet, tmmbr_send_, packet_oh_send_,
662 ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200663 int numCandidates = lengthOfBoundingSet + 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000664
Erik Språng61be2a42015-04-27 13:32:52 +0200665 // find bounding set
Erik Språngf7c57762015-12-04 10:40:35 +0100666 TMMBRSet* boundingSet = nullptr;
Erik Språng242e22b2015-05-11 10:17:43 +0200667 int numBoundingSet = tmmbr_help_.FindTMMBRBoundingSet(boundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200668 if (numBoundingSet > 0 || numBoundingSet <= numCandidates)
Erik Språng242e22b2015-05-11 10:17:43 +0200669 tmmbrOwner = tmmbr_help_.IsOwner(ssrc_, numBoundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200670 if (!tmmbrOwner) {
Erik Språngf7c57762015-12-04 10:40:35 +0100671 // Did not enter bounding set, no meaning to send this request.
672 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200673 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000674 }
Erik Språng61be2a42015-04-27 13:32:52 +0200675 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000676
Erik Språngf7c57762015-12-04 10:40:35 +0100677 if (!tmmbr_send_)
678 return nullptr;
sprang81a3e602015-08-21 05:30:11 -0700679
Erik Språngf7c57762015-12-04 10:40:35 +0100680 rtcp::Tmmbr* tmmbr = new rtcp::Tmmbr();
681 tmmbr->From(ssrc_);
682 tmmbr->To(remote_ssrc_);
683 tmmbr->WithBitrateKbps(tmmbr_send_);
684 tmmbr->WithOverhead(packet_oh_send_);
685
686 return rtc::scoped_ptr<rtcp::Tmmbr>(tmmbr);
Erik Språng61be2a42015-04-27 13:32:52 +0200687}
688
Erik Språngf7c57762015-12-04 10:40:35 +0100689rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBN(
690 const RtcpContext& ctx) {
Erik Språng242e22b2015-05-11 10:17:43 +0200691 TMMBRSet* boundingSet = tmmbr_help_.BoundingSetToSend();
Erik Språngf7c57762015-12-04 10:40:35 +0100692 if (boundingSet == nullptr)
693 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200694
Erik Språngf7c57762015-12-04 10:40:35 +0100695 rtcp::Tmmbn* tmmbn = new rtcp::Tmmbn();
696 tmmbn->From(ssrc_);
sprangd83df502015-08-27 01:05:08 -0700697 for (uint32_t i = 0; i < boundingSet->lengthOfSet(); i++) {
698 if (boundingSet->Tmmbr(i) > 0) {
Erik Språngf7c57762015-12-04 10:40:35 +0100699 tmmbn->WithTmmbr(boundingSet->Ssrc(i), boundingSet->Tmmbr(i),
700 boundingSet->PacketOH(i));
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000701 }
Erik Språng61be2a42015-04-27 13:32:52 +0200702 }
sprangd83df502015-08-27 01:05:08 -0700703
Erik Språngf7c57762015-12-04 10:40:35 +0100704 return rtc::scoped_ptr<rtcp::Tmmbn>(tmmbn);
niklase@google.com470e71d2011-07-07 08:21:25 +0000705}
706
Erik Språngf7c57762015-12-04 10:40:35 +0100707rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildAPP(const RtcpContext& ctx) {
708 rtcp::App* app = new rtcp::App();
709 app->From(ssrc_);
710 app->WithSubType(app_sub_type_);
711 app->WithName(app_name_);
712 app->WithData(app_data_.get(), app_length_);
Erik Språng521875a2015-09-01 10:11:16 +0200713
Erik Språngf7c57762015-12-04 10:40:35 +0100714 return rtc::scoped_ptr<rtcp::App>(app);
Erik Språng61be2a42015-04-27 13:32:52 +0200715}
716
Erik Språngf7c57762015-12-04 10:40:35 +0100717rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildNACK(
718 const RtcpContext& ctx) {
719 rtcp::Nack* nack = new rtcp::Nack();
720 nack->From(ssrc_);
721 nack->To(remote_ssrc_);
722 nack->WithList(ctx.nack_list_, ctx.nack_size_);
Erik Språng61be2a42015-04-27 13:32:52 +0200723
724 // Report stats.
725 NACKStringBuilder stringBuilder;
Erik Språngf7c57762015-12-04 10:40:35 +0100726 for (int idx = 0; idx < ctx.nack_size_; ++idx) {
727 stringBuilder.PushNACK(ctx.nack_list_[idx]);
728 nack_stats_.ReportRequest(ctx.nack_list_[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +0200729 }
Erik Språng61be2a42015-04-27 13:32:52 +0200730 packet_type_counter_.nack_requests = nack_stats_.requests();
731 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +0200732
733 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
734 "RTCPSender::NACK", "nacks",
735 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
736 ++packet_type_counter_.nack_packets;
737 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
738 ssrc_, packet_type_counter_.nack_packets);
739
Erik Språngf7c57762015-12-04 10:40:35 +0100740 return rtc::scoped_ptr<rtcp::Nack>(nack);
Erik Språng61be2a42015-04-27 13:32:52 +0200741}
742
Erik Språngf7c57762015-12-04 10:40:35 +0100743rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildBYE(const RtcpContext& ctx) {
744 rtcp::Bye* bye = new rtcp::Bye();
745 bye->From(ssrc_);
sprangd8ee4f92015-08-24 03:25:19 -0700746 for (uint32_t csrc : csrcs_)
Erik Språngf7c57762015-12-04 10:40:35 +0100747 bye->WithCsrc(csrc);
sprangd8ee4f92015-08-24 03:25:19 -0700748
Erik Språngf7c57762015-12-04 10:40:35 +0100749 return rtc::scoped_ptr<rtcp::Bye>(bye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000750}
751
Erik Språngf7c57762015-12-04 10:40:35 +0100752rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildReceiverReferenceTime(
753 const RtcpContext& ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200754 if (last_xr_rr_.size() >= RTCP_NUMBER_OF_SR)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000755 last_xr_rr_.erase(last_xr_rr_.begin());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000756 last_xr_rr_.insert(std::pair<uint32_t, int64_t>(
Erik Språngf7c57762015-12-04 10:40:35 +0100757 RTCPUtility::MidNtp(ctx.ntp_sec_, ctx.ntp_frac_),
758 Clock::NtpToMs(ctx.ntp_sec_, ctx.ntp_frac_)));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000759
Erik Språngf7c57762015-12-04 10:40:35 +0100760 rtcp::Xr* xr = new rtcp::Xr();
761 xr->From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000762
Erik Språngca28fdc2015-08-31 14:00:50 +0200763 rtcp::Rrtr rrtr;
Danil Chapovalovfc47ed62015-12-07 14:46:35 +0100764 rrtr.WithNtp(NtpTime(ctx.ntp_sec_, ctx.ntp_frac_));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000765
Erik Språngf7c57762015-12-04 10:40:35 +0100766 xr->WithRrtr(&rrtr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000767
Erik Språngca28fdc2015-08-31 14:00:50 +0200768 // TODO(sprang): Merge XR report sending to contain all of RRTR, DLRR, VOIP?
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000769
Erik Språngf7c57762015-12-04 10:40:35 +0100770 return rtc::scoped_ptr<rtcp::Xr>(xr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000771}
772
Erik Språngf7c57762015-12-04 10:40:35 +0100773rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildDlrr(
774 const RtcpContext& ctx) {
775 rtcp::Xr* xr = new rtcp::Xr();
776 xr->From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000777
Erik Språngca28fdc2015-08-31 14:00:50 +0200778 rtcp::Dlrr dlrr;
Erik Språngf7c57762015-12-04 10:40:35 +0100779 const RtcpReceiveTimeInfo& info = ctx.feedback_state_.last_xr_rr;
Erik Språngca28fdc2015-08-31 14:00:50 +0200780 dlrr.WithDlrrItem(info.sourceSSRC, info.lastRR, info.delaySinceLastRR);
781
Erik Språngf7c57762015-12-04 10:40:35 +0100782 xr->WithDlrr(&dlrr);
Erik Språngca28fdc2015-08-31 14:00:50 +0200783
Erik Språngf7c57762015-12-04 10:40:35 +0100784 return rtc::scoped_ptr<rtcp::Xr>(xr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000785}
786
Erik Språng242e22b2015-05-11 10:17:43 +0200787// TODO(sprang): Add a unit test for this, or remove if the code isn't used.
Erik Språngf7c57762015-12-04 10:40:35 +0100788rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildVoIPMetric(
789 const RtcpContext& context) {
790 rtcp::Xr* xr = new rtcp::Xr();
791 xr->From(ssrc_);
Erik Språngca28fdc2015-08-31 14:00:50 +0200792
793 rtcp::VoipMetric voip;
794 voip.To(remote_ssrc_);
795 voip.LossRate(xr_voip_metric_.lossRate);
796 voip.DiscardRate(xr_voip_metric_.discardRate);
797 voip.BurstDensity(xr_voip_metric_.burstDensity);
798 voip.GapDensity(xr_voip_metric_.gapDensity);
799 voip.BurstDuration(xr_voip_metric_.burstDuration);
800 voip.GapDuration(xr_voip_metric_.gapDuration);
801 voip.RoundTripDelay(xr_voip_metric_.roundTripDelay);
802 voip.EndSystemDelay(xr_voip_metric_.endSystemDelay);
803 voip.SignalLevel(xr_voip_metric_.signalLevel);
804 voip.NoiseLevel(xr_voip_metric_.noiseLevel);
805 voip.Rerl(xr_voip_metric_.RERL);
806 voip.Gmin(xr_voip_metric_.Gmin);
807 voip.Rfactor(xr_voip_metric_.Rfactor);
808 voip.ExtRfactor(xr_voip_metric_.extRfactor);
809 voip.MosLq(xr_voip_metric_.MOSLQ);
810 voip.MosCq(xr_voip_metric_.MOSCQ);
811 voip.RxConfig(xr_voip_metric_.RXconfig);
812 voip.JbNominal(xr_voip_metric_.JBnominal);
813 voip.JbMax(xr_voip_metric_.JBmax);
814 voip.JbAbsMax(xr_voip_metric_.JBabsMax);
815
Erik Språngf7c57762015-12-04 10:40:35 +0100816 xr->WithVoipMetric(&voip);
Erik Språngca28fdc2015-08-31 14:00:50 +0200817
Erik Språngf7c57762015-12-04 10:40:35 +0100818 return rtc::scoped_ptr<rtcp::Xr>(xr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000819}
820
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000821int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200822 RTCPPacketType packetType,
823 int32_t nack_size,
824 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000825 bool repeat,
826 uint64_t pictureID) {
Erik Språng242e22b2015-05-11 10:17:43 +0200827 return SendCompoundRTCP(
828 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
829 nack_size, nack_list, repeat, pictureID);
830}
831
832int32_t RTCPSender::SendCompoundRTCP(
833 const FeedbackState& feedback_state,
Erik Språngf7c57762015-12-04 10:40:35 +0100834 const std::set<RTCPPacketType>& packet_types,
Erik Språng242e22b2015-05-11 10:17:43 +0200835 int32_t nack_size,
836 const uint16_t* nack_list,
837 bool repeat,
838 uint64_t pictureID) {
Erik Språngf7c57762015-12-04 10:40:35 +0100839 PacketContainer container(transport_);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000840 {
Erik Språng242e22b2015-05-11 10:17:43 +0200841 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
pbosda903ea2015-10-02 02:36:56 -0700842 if (method_ == RtcpMode::kOff) {
Erik Språng61be2a42015-04-27 13:32:52 +0200843 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
844 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +0000845 }
Erik Språngf7c57762015-12-04 10:40:35 +0100846
847 // We need to send our NTP even if we haven't received any reports.
848 uint32_t ntp_sec;
849 uint32_t ntp_frac;
850 clock_->CurrentNtp(ntp_sec, ntp_frac);
851 RtcpContext context(feedback_state, nack_size, nack_list, repeat, pictureID,
852 ntp_sec, ntp_frac, &container);
853
854 PrepareReport(packet_types, feedback_state);
855
856 auto it = report_flags_.begin();
857 while (it != report_flags_.end()) {
858 auto builder_it = builders_.find(it->type);
859 RTC_DCHECK(builder_it != builders_.end());
860 if (it->is_volatile) {
861 report_flags_.erase(it++);
862 } else {
863 ++it;
864 }
865
866 BuilderFunc func = builder_it->second;
867 rtc::scoped_ptr<rtcp::RtcpPacket> packet = (this->*func)(context);
868 if (packet.get() == nullptr)
869 return -1;
870 container.Append(packet.release());
871 }
872
873 if (packet_type_counter_observer_ != nullptr) {
874 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
875 remote_ssrc_, packet_type_counter_);
876 }
877
878 RTC_DCHECK(AllVolatileFlagsConsumed());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000879 }
Erik Språng61be2a42015-04-27 13:32:52 +0200880
Erik Språngf7c57762015-12-04 10:40:35 +0100881 size_t bytes_sent = container.SendPackets();
882 return bytes_sent == 0 ? -1 : 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000883}
884
Erik Språngf7c57762015-12-04 10:40:35 +0100885void RTCPSender::PrepareReport(const std::set<RTCPPacketType>& packetTypes,
886 const FeedbackState& feedback_state) {
Erik Språng242e22b2015-05-11 10:17:43 +0200887 // Add all flags as volatile. Non volatile entries will not be overwritten
888 // and all new volatile flags added will be consumed by the end of this call.
889 SetFlags(packetTypes, true);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000890
Erik Språng61be2a42015-04-27 13:32:52 +0200891 if (packet_type_counter_.first_packet_time_ms == -1)
Erik Språng242e22b2015-05-11 10:17:43 +0200892 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språng61be2a42015-04-27 13:32:52 +0200893
Erik Språng242e22b2015-05-11 10:17:43 +0200894 bool generate_report;
895 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
896 // Report type already explicitly set, don't automatically populate.
897 generate_report = true;
henrikg91d6ede2015-09-17 00:24:34 -0700898 RTC_DCHECK(ConsumeFlag(kRtcpReport) == false);
Erik Språng242e22b2015-05-11 10:17:43 +0200899 } else {
900 generate_report =
pbosda903ea2015-10-02 02:36:56 -0700901 (ConsumeFlag(kRtcpReport) && method_ == RtcpMode::kReducedSize) ||
902 method_ == RtcpMode::kCompound;
Erik Språng242e22b2015-05-11 10:17:43 +0200903 if (generate_report)
904 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000905 }
906
Erik Språng0ea42d32015-06-25 14:46:16 +0200907 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
Erik Språng242e22b2015-05-11 10:17:43 +0200908 SetFlag(kRtcpSdes, true);
909
Erik Språng242e22b2015-05-11 10:17:43 +0200910 if (generate_report) {
911 if (!sending_ && xr_send_receiver_reference_time_enabled_)
912 SetFlag(kRtcpXrReceiverReferenceTime, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200913 if (feedback_state.has_last_xr_rr)
Erik Språng242e22b2015-05-11 10:17:43 +0200914 SetFlag(kRtcpXrDlrrReportBlock, true);
915
916 // generate next time to send an RTCP report
danilchap47a740b2015-12-15 00:30:07 -0800917 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000918
danilchap47a740b2015-12-15 00:30:07 -0800919 if (!audio_) {
Erik Språng242e22b2015-05-11 10:17:43 +0200920 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200921 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
922 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
923 if (send_bitrate_kbit != 0)
924 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000925 }
Erik Språng61be2a42015-04-27 13:32:52 +0200926 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
927 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
Erik Språng61be2a42015-04-27 13:32:52 +0200928 }
danilchap47a740b2015-12-15 00:30:07 -0800929 // The interval between RTCP packets is varied randomly over the
930 // range [1/2,3/2] times the calculated interval.
931 uint32_t timeToNext =
932 random_.Rand(minIntervalMs * 1 / 2, minIntervalMs * 3 / 2);
Erik Språng242e22b2015-05-11 10:17:43 +0200933 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000934
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000935 StatisticianMap statisticians =
936 receive_statistics_->GetActiveStatisticians();
937 if (!statisticians.empty()) {
Erik Språng61be2a42015-04-27 13:32:52 +0200938 for (auto it = statisticians.begin(); it != statisticians.end(); ++it) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000939 RTCPReportBlock report_block;
Erik Språngf7c57762015-12-04 10:40:35 +0100940 if (PrepareReportBlock(feedback_state, it->first, it->second,
941 &report_block)) {
danilchapdf948f02015-11-13 03:03:13 -0800942 // TODO(danilchap) AddReportBlock may fail (for 2 different reasons).
943 // Probably it shouldn't be ignored.
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200944 AddReportBlock(report_block);
Erik Språng61be2a42015-04-27 13:32:52 +0200945 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000946 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000947 }
948 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000949}
950
Erik Språngf7c57762015-12-04 10:40:35 +0100951bool RTCPSender::PrepareReportBlock(const FeedbackState& feedback_state,
952 uint32_t ssrc,
953 StreamStatistician* statistician,
954 RTCPReportBlock* report_block) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000955 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000956 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000957 if (!statistician->GetStatistics(&stats, true))
958 return false;
959 report_block->fractionLost = stats.fraction_lost;
960 report_block->cumulativeLost = stats.cumulative_lost;
danilchap162abd32015-12-10 02:39:40 -0800961 report_block->extendedHighSeqNum = stats.extended_max_sequence_number;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000962 report_block->jitter = stats.jitter;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200963 report_block->remoteSSRC = ssrc;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000964
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200965 // TODO(sprang): Do we really need separate time stamps for each report?
966 // Get our NTP as late as possible to avoid a race.
967 uint32_t ntp_secs;
968 uint32_t ntp_frac;
969 clock_->CurrentNtp(ntp_secs, ntp_frac);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000970
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200971 // Delay since last received report.
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000972 uint32_t delaySinceLastReceivedSR = 0;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000973 if ((feedback_state.last_rr_ntp_secs != 0) ||
974 (feedback_state.last_rr_ntp_frac != 0)) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200975 // Get the 16 lowest bits of seconds and the 16 highest bits of fractions.
976 uint32_t now = ntp_secs & 0x0000FFFF;
Erik Språng61be2a42015-04-27 13:32:52 +0200977 now <<= 16;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200978 now += (ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000979
Erik Språng61be2a42015-04-27 13:32:52 +0200980 uint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
981 receiveTime <<= 16;
982 receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000983
danilchap162abd32015-12-10 02:39:40 -0800984 delaySinceLastReceivedSR = now - receiveTime;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000985 }
986 report_block->delaySinceLastSR = delaySinceLastReceivedSR;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000987 report_block->lastSR = feedback_state.remote_sr;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000988 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000989}
990
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000991void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
992 assert(csrcs.size() <= kRtpCsrcSize);
Erik Språng242e22b2015-05-11 10:17:43 +0200993 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000994 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +0000995}
996
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000997int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
998 uint32_t name,
999 const uint8_t* data,
1000 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +02001001 if (length % 4 != 0) {
1002 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
1003 return -1;
1004 }
Erik Språng242e22b2015-05-11 10:17:43 +02001005 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +00001006
Erik Språng242e22b2015-05-11 10:17:43 +02001007 SetFlag(kRtcpApp, true);
1008 app_sub_type_ = subType;
1009 app_name_ = name;
1010 app_data_.reset(new uint8_t[length]);
1011 app_length_ = length;
1012 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +02001013 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001014}
1015
Erik Språng61be2a42015-04-27 13:32:52 +02001016int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
Erik Språng242e22b2015-05-11 10:17:43 +02001017 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1018 memcpy(&xr_voip_metric_, VoIPMetric, sizeof(RTCPVoIPMetric));
niklase@google.com470e71d2011-07-07 08:21:25 +00001019
Erik Språng242e22b2015-05-11 10:17:43 +02001020 SetFlag(kRtcpXrVoipMetric, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001021 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001022}
1023
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001024void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +02001025 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1026 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001027}
1028
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00001029bool RTCPSender::RtcpXrReceiverReferenceTime() const {
Erik Språng242e22b2015-05-11 10:17:43 +02001030 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1031 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00001032}
1033
niklase@google.com470e71d2011-07-07 08:21:25 +00001034// no callbacks allowed inside this function
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001035int32_t RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
1036 uint32_t maxBitrateKbit) {
Erik Språng242e22b2015-05-11 10:17:43 +02001037 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +00001038
Erik Språng242e22b2015-05-11 10:17:43 +02001039 if (0 == tmmbr_help_.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit)) {
1040 SetFlag(kRtcpTmmbn, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001041 return 0;
1042 }
1043 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001044}
Erik Språng61be2a42015-04-27 13:32:52 +02001045
Erik Språng242e22b2015-05-11 10:17:43 +02001046void RTCPSender::SetFlag(RTCPPacketType type, bool is_volatile) {
1047 report_flags_.insert(ReportFlag(type, is_volatile));
1048}
1049
1050void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
1051 bool is_volatile) {
1052 for (RTCPPacketType type : types)
1053 SetFlag(type, is_volatile);
1054}
1055
1056bool RTCPSender::IsFlagPresent(RTCPPacketType type) const {
1057 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
1058}
1059
1060bool RTCPSender::ConsumeFlag(RTCPPacketType type, bool forced) {
1061 auto it = report_flags_.find(ReportFlag(type, false));
1062 if (it == report_flags_.end())
1063 return false;
1064 if (it->is_volatile || forced)
1065 report_flags_.erase((it));
1066 return true;
1067}
1068
1069bool RTCPSender::AllVolatileFlagsConsumed() const {
1070 for (const ReportFlag& flag : report_flags_) {
1071 if (flag.is_volatile)
1072 return false;
1073 }
1074 return true;
1075}
1076
sprang233bd872015-09-08 13:25:16 -07001077bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
sprang233bd872015-09-08 13:25:16 -07001078 class Sender : public rtcp::RtcpPacket::PacketReadyCallback {
1079 public:
danilchap6db6cdc2015-12-15 02:54:47 -08001080 explicit Sender(Transport* transport)
Peter Boströmac547a62015-09-17 23:03:57 +02001081 : transport_(transport), send_failure_(false) {}
sprang233bd872015-09-08 13:25:16 -07001082
1083 void OnPacketReady(uint8_t* data, size_t length) override {
pbos2d566682015-09-28 09:59:31 -07001084 if (!transport_->SendRtcp(data, length))
sprang233bd872015-09-08 13:25:16 -07001085 send_failure_ = true;
1086 }
1087
1088 Transport* const transport_;
sprang233bd872015-09-08 13:25:16 -07001089 bool send_failure_;
sprang86fd9ed2015-09-29 04:45:43 -07001090 } sender(transport_);
sprang233bd872015-09-08 13:25:16 -07001091
1092 uint8_t buffer[IP_PACKET_SIZE];
1093 return packet.BuildExternalBuffer(buffer, IP_PACKET_SIZE, &sender) &&
1094 !sender.send_failure_;
1095}
1096
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001097} // namespace webrtc