blob: eea1c81b79a06c0a094dab515f66e556c5cb9d2e [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"
sprang233bd872015-09-08 13:25:16 -070028#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
tommie4f96502015-10-20 23:00:48 -070029#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010030#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000031
niklase@google.com470e71d2011-07-07 08:21:25 +000032namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000033
34using RTCPUtility::RTCPCnameInformation;
35
Erik Språng61be2a42015-04-27 13:32:52 +020036NACKStringBuilder::NACKStringBuilder()
Erik Språng242e22b2015-05-11 10:17:43 +020037 : stream_(""), count_(0), prevNack_(0), consecutive_(false) {
edjee@google.com79b02892013-04-04 19:43:34 +000038}
39
pbos@webrtc.orgf3e4cee2013-07-31 15:17:19 +000040NACKStringBuilder::~NACKStringBuilder() {}
41
pbos@webrtc.org2f446732013-04-08 11:08:41 +000042void NACKStringBuilder::PushNACK(uint16_t nack)
edjee@google.com79b02892013-04-04 19:43:34 +000043{
Erik Språng242e22b2015-05-11 10:17:43 +020044 if (count_ == 0) {
45 stream_ << nack;
46 } else if (nack == prevNack_ + 1) {
47 consecutive_ = true;
Erik Språng61be2a42015-04-27 13:32:52 +020048 } else {
Erik Språng242e22b2015-05-11 10:17:43 +020049 if (consecutive_) {
50 stream_ << "-" << prevNack_;
51 consecutive_ = false;
edjee@google.com79b02892013-04-04 19:43:34 +000052 }
Erik Språng242e22b2015-05-11 10:17:43 +020053 stream_ << "," << nack;
Erik Språng61be2a42015-04-27 13:32:52 +020054 }
Erik Språng242e22b2015-05-11 10:17:43 +020055 count_++;
56 prevNack_ = nack;
edjee@google.com79b02892013-04-04 19:43:34 +000057}
58
Erik Språng61be2a42015-04-27 13:32:52 +020059std::string NACKStringBuilder::GetResult() {
Erik Språng242e22b2015-05-11 10:17:43 +020060 if (consecutive_) {
61 stream_ << "-" << prevNack_;
62 consecutive_ = false;
Erik Språng61be2a42015-04-27 13:32:52 +020063 }
Erik Språng242e22b2015-05-11 10:17:43 +020064 return stream_.str();
edjee@google.com79b02892013-04-04 19:43:34 +000065}
66
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000067RTCPSender::FeedbackState::FeedbackState()
68 : send_payload_type(0),
69 frequency_hz(0),
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +000070 packets_sent(0),
71 media_bytes_sent(0),
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000072 send_bitrate(0),
73 last_rr_ntp_secs(0),
74 last_rr_ntp_frac(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000075 remote_sr(0),
Erik Språng61be2a42015-04-27 13:32:52 +020076 has_last_xr_rr(false),
77 module(nullptr) {
78}
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000079
Erik Språng242e22b2015-05-11 10:17:43 +020080struct RTCPSender::RtcpContext {
81 RtcpContext(const FeedbackState& feedback_state,
82 int32_t nack_size,
83 const uint16_t* nack_list,
84 bool repeat,
85 uint64_t picture_id,
86 uint8_t* buffer,
87 uint32_t buffer_size)
88 : feedback_state(feedback_state),
89 nack_size(nack_size),
90 nack_list(nack_list),
91 repeat(repeat),
92 picture_id(picture_id),
93 buffer(buffer),
94 buffer_size(buffer_size),
95 ntp_sec(0),
96 ntp_frac(0),
Erik Språng242e22b2015-05-11 10:17:43 +020097 position(0) {}
98
99 uint8_t* AllocateData(uint32_t bytes) {
henrikg91d6ede2015-09-17 00:24:34 -0700100 RTC_DCHECK_LE(position + bytes, buffer_size);
Erik Språng242e22b2015-05-11 10:17:43 +0200101 uint8_t* ptr = &buffer[position];
102 position += bytes;
103 return ptr;
104 }
105
106 const FeedbackState& feedback_state;
107 int32_t nack_size;
108 const uint16_t* nack_list;
109 bool repeat;
110 uint64_t picture_id;
111 uint8_t* buffer;
112 uint32_t buffer_size;
113 uint32_t ntp_sec;
114 uint32_t ntp_frac;
Erik Språng242e22b2015-05-11 10:17:43 +0200115 uint32_t position;
116};
117
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200118// TODO(sprang): Once all builders use RtcpPacket, call SendToNetwork() here.
119class RTCPSender::PacketBuiltCallback
120 : public rtcp::RtcpPacket::PacketReadyCallback {
121 public:
122 PacketBuiltCallback(RtcpContext* context) : context_(context) {}
123 virtual ~PacketBuiltCallback() {}
124 void OnPacketReady(uint8_t* data, size_t length) override {
125 context_->position += length;
126 }
Erik Språng72aa9a62015-07-31 16:16:02 +0200127 bool BuildPacket(const rtcp::RtcpPacket& packet) {
128 return packet.BuildExternalBuffer(
129 &context_->buffer[context_->position],
130 context_->buffer_size - context_->position, this);
131 }
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200132
133 private:
134 RtcpContext* const context_;
135};
136
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000137RTCPSender::RTCPSender(
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000138 bool audio,
139 Clock* clock,
140 ReceiveStatistics* receive_statistics,
sprang86fd9ed2015-09-29 04:45:43 -0700141 RtcpPacketTypeCounterObserver* packet_type_counter_observer,
142 Transport* outgoing_transport)
Peter Boströmac547a62015-09-17 23:03:57 +0200143 : audio_(audio),
Erik Språng242e22b2015-05-11 10:17:43 +0200144 clock_(clock),
pbosda903ea2015-10-02 02:36:56 -0700145 method_(RtcpMode::kOff),
sprang86fd9ed2015-09-29 04:45:43 -0700146 transport_(outgoing_transport),
niklase@google.com470e71d2011-07-07 08:21:25 +0000147
Erik Språng242e22b2015-05-11 10:17:43 +0200148 critical_section_rtcp_sender_(
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000149 CriticalSectionWrapper::CreateCriticalSection()),
Erik Språng242e22b2015-05-11 10:17:43 +0200150 using_nack_(false),
151 sending_(false),
152 remb_enabled_(false),
Erik Språng242e22b2015-05-11 10:17:43 +0200153 next_time_to_send_rtcp_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000154 start_timestamp_(0),
155 last_rtp_timestamp_(0),
156 last_frame_capture_time_ms_(-1),
Erik Språng242e22b2015-05-11 10:17:43 +0200157 ssrc_(0),
158 remote_ssrc_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000159 receive_statistics_(receive_statistics),
niklase@google.com470e71d2011-07-07 08:21:25 +0000160
Erik Språng242e22b2015-05-11 10:17:43 +0200161 sequence_number_fir_(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000162
Erik Språng242e22b2015-05-11 10:17:43 +0200163 remb_bitrate_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000164
Erik Språng242e22b2015-05-11 10:17:43 +0200165 tmmbr_help_(),
166 tmmbr_send_(0),
167 packet_oh_send_(0),
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000168
Erik Språng242e22b2015-05-11 10:17:43 +0200169 app_sub_type_(0),
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200170 app_name_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200171 app_data_(nullptr),
172 app_length_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000173
Erik Språng242e22b2015-05-11 10:17:43 +0200174 xr_send_receiver_reference_time_enabled_(false),
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000175 packet_type_counter_observer_(packet_type_counter_observer) {
Erik Språng242e22b2015-05-11 10:17:43 +0200176 memset(last_send_report_, 0, sizeof(last_send_report_));
177 memset(last_rtcp_time_, 0, sizeof(last_rtcp_time_));
sprang86fd9ed2015-09-29 04:45:43 -0700178 RTC_DCHECK(transport_ != nullptr);
Erik Språng242e22b2015-05-11 10:17:43 +0200179
180 builders_[kRtcpSr] = &RTCPSender::BuildSR;
181 builders_[kRtcpRr] = &RTCPSender::BuildRR;
Erik Språng0ea42d32015-06-25 14:46:16 +0200182 builders_[kRtcpSdes] = &RTCPSender::BuildSDES;
Erik Språng242e22b2015-05-11 10:17:43 +0200183 builders_[kRtcpPli] = &RTCPSender::BuildPLI;
184 builders_[kRtcpFir] = &RTCPSender::BuildFIR;
185 builders_[kRtcpSli] = &RTCPSender::BuildSLI;
186 builders_[kRtcpRpsi] = &RTCPSender::BuildRPSI;
187 builders_[kRtcpRemb] = &RTCPSender::BuildREMB;
188 builders_[kRtcpBye] = &RTCPSender::BuildBYE;
189 builders_[kRtcpApp] = &RTCPSender::BuildAPP;
190 builders_[kRtcpTmmbr] = &RTCPSender::BuildTMMBR;
191 builders_[kRtcpTmmbn] = &RTCPSender::BuildTMMBN;
192 builders_[kRtcpNack] = &RTCPSender::BuildNACK;
193 builders_[kRtcpXrVoipMetric] = &RTCPSender::BuildVoIPMetric;
194 builders_[kRtcpXrReceiverReferenceTime] =
195 &RTCPSender::BuildReceiverReferenceTime;
196 builders_[kRtcpXrDlrrReportBlock] = &RTCPSender::BuildDlrr;
niklase@google.com470e71d2011-07-07 08:21:25 +0000197}
198
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000199RTCPSender::~RTCPSender() {
niklase@google.com470e71d2011-07-07 08:21:25 +0000200}
201
pbosda903ea2015-10-02 02:36:56 -0700202RtcpMode RTCPSender::Status() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200203 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
204 return method_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000205}
206
pbosda903ea2015-10-02 02:36:56 -0700207void RTCPSender::SetRTCPStatus(RtcpMode method) {
Erik Språng242e22b2015-05-11 10:17:43 +0200208 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
209 method_ = method;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000210
pbosda903ea2015-10-02 02:36:56 -0700211 if (method == RtcpMode::kOff)
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000212 return;
Erik Språng242e22b2015-05-11 10:17:43 +0200213 next_time_to_send_rtcp_ =
214 clock_->TimeInMilliseconds() +
215 (audio_ ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000216}
217
Erik Språng61be2a42015-04-27 13:32:52 +0200218bool RTCPSender::Sending() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200219 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
220 return sending_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000221}
222
Erik Språng61be2a42015-04-27 13:32:52 +0200223int32_t RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
224 bool sending) {
225 bool sendRTCPBye = false;
226 {
Erik Språng242e22b2015-05-11 10:17:43 +0200227 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000228
pbosda903ea2015-10-02 02:36:56 -0700229 if (method_ != RtcpMode::kOff) {
Erik Språng242e22b2015-05-11 10:17:43 +0200230 if (sending == false && sending_ == true) {
Erik Språng61be2a42015-04-27 13:32:52 +0200231 // Trigger RTCP bye
232 sendRTCPBye = true;
233 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000234 }
Erik Språng242e22b2015-05-11 10:17:43 +0200235 sending_ = sending;
Erik Språng61be2a42015-04-27 13:32:52 +0200236 }
237 if (sendRTCPBye)
238 return SendRTCP(feedback_state, kRtcpBye);
239 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000240}
241
Erik Språng61be2a42015-04-27 13:32:52 +0200242bool RTCPSender::REMB() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200243 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
244 return remb_enabled_;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000245}
246
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000247void RTCPSender::SetREMBStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200248 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
249 remb_enabled_ = enable;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000250}
251
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000252void RTCPSender::SetREMBData(uint32_t bitrate,
253 const std::vector<uint32_t>& ssrcs) {
Erik Språng242e22b2015-05-11 10:17:43 +0200254 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
255 remb_bitrate_ = bitrate;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000256 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000257
Erik Språng242e22b2015-05-11 10:17:43 +0200258 if (remb_enabled_)
259 SetFlag(kRtcpRemb, false);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000260 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
261 // throttled by the caller.
Erik Språng242e22b2015-05-11 10:17:43 +0200262 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000263}
264
Erik Språng61be2a42015-04-27 13:32:52 +0200265bool RTCPSender::TMMBR() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200266 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
267 return IsFlagPresent(RTCPPacketType::kRtcpTmmbr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000268}
269
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000270void RTCPSender::SetTMMBRStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200271 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
272 if (enable) {
273 SetFlag(RTCPPacketType::kRtcpTmmbr, false);
274 } else {
275 ConsumeFlag(RTCPPacketType::kRtcpTmmbr, true);
276 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000277}
278
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000279void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
Erik Språng242e22b2015-05-11 10:17:43 +0200280 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000281 start_timestamp_ = start_timestamp;
282}
283
284void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
285 int64_t capture_time_ms) {
Erik Språng242e22b2015-05-11 10:17:43 +0200286 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000287 last_rtp_timestamp_ = rtp_timestamp;
288 if (capture_time_ms < 0) {
289 // We don't currently get a capture time from VoiceEngine.
Erik Språng242e22b2015-05-11 10:17:43 +0200290 last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000291 } else {
292 last_frame_capture_time_ms_ = capture_time_ms;
293 }
294}
295
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000296void RTCPSender::SetSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200297 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000298
Erik Språng242e22b2015-05-11 10:17:43 +0200299 if (ssrc_ != 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200300 // not first SetSSRC, probably due to a collision
301 // schedule a new RTCP report
302 // make sure that we send a RTP packet
Erik Språng242e22b2015-05-11 10:17:43 +0200303 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
Erik Språng61be2a42015-04-27 13:32:52 +0200304 }
Erik Språng242e22b2015-05-11 10:17:43 +0200305 ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000306}
307
Erik Språng61be2a42015-04-27 13:32:52 +0200308void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200309 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
310 remote_ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000311}
312
Peter Boström9ba52f82015-06-01 14:12:28 +0200313int32_t RTCPSender::SetCNAME(const char* c_name) {
314 if (!c_name)
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000315 return -1;
316
henrikg91d6ede2015-09-17 00:24:34 -0700317 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
Erik Språng242e22b2015-05-11 10:17:43 +0200318 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200319 cname_ = c_name;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000320 return 0;
321}
322
Erik Språng0ea42d32015-06-25 14:46:16 +0200323int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC, const char* c_name) {
324 assert(c_name);
henrikg91d6ede2015-09-17 00:24:34 -0700325 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
Erik Språng242e22b2015-05-11 10:17:43 +0200326 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200327 if (csrc_cnames_.size() >= kRtpCsrcSize)
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000328 return -1;
Erik Språng0ea42d32015-06-25 14:46:16 +0200329
330 csrc_cnames_[SSRC] = c_name;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000331 return 0;
332}
333
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000334int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
Erik Språng242e22b2015-05-11 10:17:43 +0200335 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200336 auto it = csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000337
Erik Språng242e22b2015-05-11 10:17:43 +0200338 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000339 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200340
Erik Språng242e22b2015-05-11 10:17:43 +0200341 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000342 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000343}
344
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000345bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
niklase@google.com470e71d2011-07-07 08:21:25 +0000346/*
347 For audio we use a fix 5 sec interval
348
349 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000350 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
351 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000352
353
354From RFC 3550
355
356 MAX RTCP BW is 5% if the session BW
357 A send report is approximately 65 bytes inc CNAME
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000358 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000359
360 The RECOMMENDED value for the reduced minimum in seconds is 360
361 divided by the session bandwidth in kilobits/second. This minimum
362 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
363
364 If the participant has not yet sent an RTCP packet (the variable
365 initial is true), the constant Tmin is set to 2.5 seconds, else it
366 is set to 5 seconds.
367
368 The interval between RTCP packets is varied randomly over the
369 range [0.5,1.5] times the calculated interval to avoid unintended
370 synchronization of all participants
371
372 if we send
373 If the participant is a sender (we_sent true), the constant C is
374 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
375 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
376 number of senders.
377
378 if we receive only
379 If we_sent is not true, the constant C is set
380 to the average RTCP packet size divided by 75% of the RTCP
381 bandwidth. The constant n is set to the number of receivers
382 (members - senders). If the number of senders is greater than
383 25%, senders and receivers are treated together.
384
385 reconsideration NOT required for peer-to-peer
386 "timer reconsideration" is
387 employed. This algorithm implements a simple back-off mechanism
388 which causes users to hold back RTCP packet transmission if the
389 group sizes are increasing.
390
391 n = number of members
392 C = avg_size/(rtcpBW/4)
393
394 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
395
396 4. The calculated interval T is set to a number uniformly distributed
397 between 0.5 and 1.5 times the deterministic calculated interval.
398
399 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
400 for the fact that the timer reconsideration algorithm converges to
401 a value of the RTCP bandwidth below the intended average
402*/
403
Erik Språng242e22b2015-05-11 10:17:43 +0200404 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000405
Erik Språng242e22b2015-05-11 10:17:43 +0200406 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
xians@webrtc.org8738d272011-11-25 13:43:53 +0000407
pbosda903ea2015-10-02 02:36:56 -0700408 if (method_ == RtcpMode::kOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000409 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000410
Erik Språng242e22b2015-05-11 10:17:43 +0200411 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200412 // for video key-frames we want to send the RTCP before the large key-frame
413 // if we have a 100 ms margin
414 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
415 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000416
Erik Språng242e22b2015-05-11 10:17:43 +0200417 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200418 return true;
419 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200420 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200421 // wrap
422 return true;
423 }
424 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000425}
426
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000427int64_t RTCPSender::SendTimeOfSendReport(uint32_t sendReport) {
Erik Språng242e22b2015-05-11 10:17:43 +0200428 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000429
Erik Språng61be2a42015-04-27 13:32:52 +0200430 // This is only saved when we are the sender
Erik Språng242e22b2015-05-11 10:17:43 +0200431 if ((last_send_report_[0] == 0) || (sendReport == 0)) {
Erik Språng61be2a42015-04-27 13:32:52 +0200432 return 0; // will be ignored
433 } else {
434 for (int i = 0; i < RTCP_NUMBER_OF_SR; ++i) {
Erik Språng242e22b2015-05-11 10:17:43 +0200435 if (last_send_report_[i] == sendReport)
436 return last_rtcp_time_[i];
niklase@google.com470e71d2011-07-07 08:21:25 +0000437 }
Erik Språng61be2a42015-04-27 13:32:52 +0200438 }
439 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000440}
441
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000442bool RTCPSender::SendTimeOfXrRrReport(uint32_t mid_ntp,
443 int64_t* time_ms) const {
Erik Språng242e22b2015-05-11 10:17:43 +0200444 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000445
446 if (last_xr_rr_.empty()) {
447 return false;
448 }
449 std::map<uint32_t, int64_t>::const_iterator it = last_xr_rr_.find(mid_ntp);
450 if (it == last_xr_rr_.end()) {
451 return false;
452 }
453 *time_ms = it->second;
454 return true;
455}
456
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200457int32_t RTCPSender::AddReportBlock(const RTCPReportBlock& report_block) {
458 if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000459 LOG(LS_WARNING) << "Too many report blocks.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000460 return -1;
461 }
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200462 rtcp::ReportBlock* block = &report_blocks_[report_block.remoteSSRC];
463 block->To(report_block.remoteSSRC);
464 block->WithFractionLost(report_block.fractionLost);
danilchapdf948f02015-11-13 03:03:13 -0800465 if (!block->WithCumulativeLost(report_block.cumulativeLost)) {
466 LOG(LS_WARNING) << "Cumulative lost is oversized.";
467 return -1;
468 }
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200469 block->WithExtHighestSeqNum(report_block.extendedHighSeqNum);
470 block->WithJitter(report_block.jitter);
471 block->WithLastSr(report_block.lastSR);
472 block->WithDelayLastSr(report_block.delaySinceLastSR);
473
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000474 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000475}
476
Erik Språng242e22b2015-05-11 10:17:43 +0200477RTCPSender::BuildResult RTCPSender::BuildSR(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200478 for (int i = (RTCP_NUMBER_OF_SR - 2); i >= 0; i--) {
479 // shift old
Erik Språng242e22b2015-05-11 10:17:43 +0200480 last_send_report_[i + 1] = last_send_report_[i];
481 last_rtcp_time_[i + 1] = last_rtcp_time_[i];
Erik Språng61be2a42015-04-27 13:32:52 +0200482 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000483
Erik Språng242e22b2015-05-11 10:17:43 +0200484 last_rtcp_time_[0] = Clock::NtpToMs(ctx->ntp_sec, ctx->ntp_frac);
485 last_send_report_[0] = (ctx->ntp_sec << 16) + (ctx->ntp_frac >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000486
Erik Språng61be2a42015-04-27 13:32:52 +0200487 // The timestamp of this RTCP packet should be estimated as the timestamp of
488 // the frame being captured at this moment. We are calculating that
489 // timestamp as the last frame's timestamp + the time since the last frame
490 // was captured.
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200491 uint32_t rtp_timestamp =
492 start_timestamp_ + last_rtp_timestamp_ +
493 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) *
494 (ctx->feedback_state.frequency_hz / 1000);
niklase@google.com470e71d2011-07-07 08:21:25 +0000495
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200496 rtcp::SenderReport report;
497 report.From(ssrc_);
498 report.WithNtpSec(ctx->ntp_sec);
499 report.WithNtpFrac(ctx->ntp_frac);
500 report.WithRtpTimestamp(rtp_timestamp);
501 report.WithPacketCount(ctx->feedback_state.packets_sent);
502 report.WithOctetCount(ctx->feedback_state.media_bytes_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000503
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200504 for (auto it : report_blocks_)
505 report.WithReportBlock(it.second);
niklase@google.com470e71d2011-07-07 08:21:25 +0000506
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200507 PacketBuiltCallback callback(ctx);
Erik Språng72aa9a62015-07-31 16:16:02 +0200508 if (!callback.BuildPacket(report))
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200509 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000510
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200511 report_blocks_.clear();
Erik Språng242e22b2015-05-11 10:17:43 +0200512 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000513}
514
Erik Språng0ea42d32015-06-25 14:46:16 +0200515RTCPSender::BuildResult RTCPSender::BuildSDES(RtcpContext* ctx) {
516 size_t length_cname = cname_.length();
henrikg91d6ede2015-09-17 00:24:34 -0700517 RTC_CHECK_LT(length_cname, static_cast<size_t>(RTCP_CNAME_SIZE));
niklase@google.com470e71d2011-07-07 08:21:25 +0000518
Erik Språng0ea42d32015-06-25 14:46:16 +0200519 rtcp::Sdes sdes;
520 sdes.WithCName(ssrc_, cname_);
521
522 for (const auto it : csrc_cnames_)
523 sdes.WithCName(it.first, it.second);
524
525 PacketBuiltCallback callback(ctx);
Erik Språng72aa9a62015-07-31 16:16:02 +0200526 if (!callback.BuildPacket(sdes))
Erik Språng242e22b2015-05-11 10:17:43 +0200527 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000528
Erik Språng242e22b2015-05-11 10:17:43 +0200529 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000530}
531
Erik Språng242e22b2015-05-11 10:17:43 +0200532RTCPSender::BuildResult RTCPSender::BuildRR(RtcpContext* ctx) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200533 rtcp::ReceiverReport report;
534 report.From(ssrc_);
535 for (auto it : report_blocks_)
536 report.WithReportBlock(it.second);
537
538 PacketBuiltCallback callback(ctx);
Erik Språng72aa9a62015-07-31 16:16:02 +0200539 if (!callback.BuildPacket(report))
Erik Språng242e22b2015-05-11 10:17:43 +0200540 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200541
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200542 report_blocks_.clear();
Erik Språng242e22b2015-05-11 10:17:43 +0200543
544 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000545}
546
Erik Språng242e22b2015-05-11 10:17:43 +0200547RTCPSender::BuildResult RTCPSender::BuildPLI(RtcpContext* ctx) {
Erik Språng72aa9a62015-07-31 16:16:02 +0200548 rtcp::Pli pli;
549 pli.From(ssrc_);
550 pli.To(remote_ssrc_);
551
552 PacketBuiltCallback callback(ctx);
553 if (!callback.BuildPacket(pli))
Erik Språng242e22b2015-05-11 10:17:43 +0200554 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200555
Erik Språng242e22b2015-05-11 10:17:43 +0200556 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
557 "RTCPSender::PLI");
558 ++packet_type_counter_.pli_packets;
559 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
560 ssrc_, packet_type_counter_.pli_packets);
561
562 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +0200563}
564
Erik Språng242e22b2015-05-11 10:17:43 +0200565RTCPSender::BuildResult RTCPSender::BuildFIR(RtcpContext* ctx) {
Erik Språng242e22b2015-05-11 10:17:43 +0200566 if (!ctx->repeat)
sprang62dae192015-08-05 02:35:35 -0700567 ++sequence_number_fir_; // Do not increase if repetition.
niklase@google.com470e71d2011-07-07 08:21:25 +0000568
sprang62dae192015-08-05 02:35:35 -0700569 rtcp::Fir fir;
570 fir.From(ssrc_);
571 fir.To(remote_ssrc_);
572 fir.WithCommandSeqNum(sequence_number_fir_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000573
sprang62dae192015-08-05 02:35:35 -0700574 PacketBuiltCallback callback(ctx);
575 if (!callback.BuildPacket(fir))
576 return BuildResult::kTruncated;
Erik Språng242e22b2015-05-11 10:17:43 +0200577
578 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
579 "RTCPSender::FIR");
580 ++packet_type_counter_.fir_packets;
581 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
582 ssrc_, packet_type_counter_.fir_packets);
583
584 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000585}
586
587/*
588 0 1 2 3
589 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
590 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
591 | First | Number | PictureID |
592 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
593*/
Erik Språng242e22b2015-05-11 10:17:43 +0200594RTCPSender::BuildResult RTCPSender::BuildSLI(RtcpContext* ctx) {
sprang0365a272015-08-11 01:02:37 -0700595 rtcp::Sli sli;
596 sli.From(ssrc_);
597 sli.To(remote_ssrc_);
598 // Crop picture id to 6 least significant bits.
599 sli.WithPictureId(ctx->picture_id & 0x3F);
600 sli.WithFirstMb(0);
601 sli.WithNumberOfMb(0x1FFF); // 13 bits, only ones for now.
602
603 PacketBuiltCallback callback(ctx);
604 if (!callback.BuildPacket(sli))
Erik Språng242e22b2015-05-11 10:17:43 +0200605 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000606
Erik Språng242e22b2015-05-11 10:17:43 +0200607 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000608}
609
610/*
611 0 1 2 3
612 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
613 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
614 | PB |0| Payload Type| Native RPSI bit string |
615 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
616 | defined per codec ... | Padding (0) |
617 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
618*/
619/*
620* Note: not generic made for VP8
621*/
Erik Språng242e22b2015-05-11 10:17:43 +0200622RTCPSender::BuildResult RTCPSender::BuildRPSI(RtcpContext* ctx) {
623 if (ctx->feedback_state.send_payload_type == 0xFF)
624 return BuildResult::kError;
625
sprangcf7f54d2015-08-13 04:37:42 -0700626 rtcp::Rpsi rpsi;
627 rpsi.From(ssrc_);
628 rpsi.To(remote_ssrc_);
629 rpsi.WithPayloadType(ctx->feedback_state.send_payload_type);
630 rpsi.WithPictureId(ctx->picture_id);
631
632 PacketBuiltCallback callback(ctx);
633 if (!callback.BuildPacket(rpsi))
Erik Språng242e22b2015-05-11 10:17:43 +0200634 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000635
Erik Språng242e22b2015-05-11 10:17:43 +0200636 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000637}
638
Erik Språng242e22b2015-05-11 10:17:43 +0200639RTCPSender::BuildResult RTCPSender::BuildREMB(RtcpContext* ctx) {
sprangdd4edc52015-08-21 04:21:51 -0700640 rtcp::Remb remb;
641 remb.From(ssrc_);
642 for (uint32_t ssrc : remb_ssrcs_)
643 remb.AppliesTo(ssrc);
644 remb.WithBitrateBps(remb_bitrate_);
645
646 PacketBuiltCallback callback(ctx);
647 if (!callback.BuildPacket(remb))
Erik Språng242e22b2015-05-11 10:17:43 +0200648 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200649
Erik Språng242e22b2015-05-11 10:17:43 +0200650 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
651 "RTCPSender::REMB");
652
653 return BuildResult::kSuccess;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000654}
655
Erik Språng61be2a42015-04-27 13:32:52 +0200656void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
Erik Språng242e22b2015-05-11 10:17:43 +0200657 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
658 tmmbr_send_ = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000659}
660
Erik Språng242e22b2015-05-11 10:17:43 +0200661RTCPSender::BuildResult RTCPSender::BuildTMMBR(RtcpContext* ctx) {
662 if (ctx->feedback_state.module == NULL)
663 return BuildResult::kError;
Erik Språng61be2a42015-04-27 13:32:52 +0200664 // Before sending the TMMBR check the received TMMBN, only an owner is
665 // allowed to raise the bitrate:
666 // * If the sender is an owner of the TMMBN -> send TMMBR
667 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000668
Erik Språng61be2a42015-04-27 13:32:52 +0200669 // get current bounding set from RTCP receiver
670 bool tmmbrOwner = false;
671 // store in candidateSet, allocates one extra slot
Erik Språng242e22b2015-05-11 10:17:43 +0200672 TMMBRSet* candidateSet = tmmbr_help_.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000673
Erik Språng242e22b2015-05-11 10:17:43 +0200674 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
675 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
Erik Språng61be2a42015-04-27 13:32:52 +0200676 // since RTCPreceiver is not doing the reverse we should be fine
677 int32_t lengthOfBoundingSet =
Erik Språng242e22b2015-05-11 10:17:43 +0200678 ctx->feedback_state.module->BoundingSet(tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +0000679
Erik Språng61be2a42015-04-27 13:32:52 +0200680 if (lengthOfBoundingSet > 0) {
681 for (int32_t i = 0; i < lengthOfBoundingSet; i++) {
Erik Språng242e22b2015-05-11 10:17:43 +0200682 if (candidateSet->Tmmbr(i) == tmmbr_send_ &&
683 candidateSet->PacketOH(i) == packet_oh_send_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200684 // do not send the same tuple
Erik Språng242e22b2015-05-11 10:17:43 +0200685 return BuildResult::kAborted;
Erik Språng61be2a42015-04-27 13:32:52 +0200686 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000687 }
Erik Språng61be2a42015-04-27 13:32:52 +0200688 if (!tmmbrOwner) {
689 // use received bounding set as candidate set
690 // add current tuple
Erik Språng242e22b2015-05-11 10:17:43 +0200691 candidateSet->SetEntry(lengthOfBoundingSet, tmmbr_send_, packet_oh_send_,
692 ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200693 int numCandidates = lengthOfBoundingSet + 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000694
Erik Språng61be2a42015-04-27 13:32:52 +0200695 // find bounding set
696 TMMBRSet* boundingSet = NULL;
Erik Språng242e22b2015-05-11 10:17:43 +0200697 int numBoundingSet = tmmbr_help_.FindTMMBRBoundingSet(boundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200698 if (numBoundingSet > 0 || numBoundingSet <= numCandidates)
Erik Språng242e22b2015-05-11 10:17:43 +0200699 tmmbrOwner = tmmbr_help_.IsOwner(ssrc_, numBoundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200700 if (!tmmbrOwner) {
701 // did not enter bounding set, no meaning to send this request
Erik Språng242e22b2015-05-11 10:17:43 +0200702 return BuildResult::kAborted;
Erik Språng61be2a42015-04-27 13:32:52 +0200703 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000704 }
Erik Språng61be2a42015-04-27 13:32:52 +0200705 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000706
Erik Språng242e22b2015-05-11 10:17:43 +0200707 if (tmmbr_send_) {
sprang81a3e602015-08-21 05:30:11 -0700708 rtcp::Tmmbr tmmbr;
709 tmmbr.From(ssrc_);
710 tmmbr.To(remote_ssrc_);
711 tmmbr.WithBitrateKbps(tmmbr_send_);
712 tmmbr.WithOverhead(packet_oh_send_);
713
714 PacketBuiltCallback callback(ctx);
715 if (!callback.BuildPacket(tmmbr))
Erik Språng242e22b2015-05-11 10:17:43 +0200716 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200717 }
Erik Språng242e22b2015-05-11 10:17:43 +0200718 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +0200719}
720
Erik Språng242e22b2015-05-11 10:17:43 +0200721RTCPSender::BuildResult RTCPSender::BuildTMMBN(RtcpContext* ctx) {
722 TMMBRSet* boundingSet = tmmbr_help_.BoundingSetToSend();
Erik Språng61be2a42015-04-27 13:32:52 +0200723 if (boundingSet == NULL)
Erik Språng242e22b2015-05-11 10:17:43 +0200724 return BuildResult::kError;
Erik Språng61be2a42015-04-27 13:32:52 +0200725
sprangd83df502015-08-27 01:05:08 -0700726 rtcp::Tmmbn tmmbn;
727 tmmbn.From(ssrc_);
728 for (uint32_t i = 0; i < boundingSet->lengthOfSet(); i++) {
729 if (boundingSet->Tmmbr(i) > 0) {
730 tmmbn.WithTmmbr(boundingSet->Ssrc(i), boundingSet->Tmmbr(i),
731 boundingSet->PacketOH(i));
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000732 }
Erik Språng61be2a42015-04-27 13:32:52 +0200733 }
sprangd83df502015-08-27 01:05:08 -0700734
735 PacketBuiltCallback callback(ctx);
736 if (!callback.BuildPacket(tmmbn))
737 return BuildResult::kTruncated;
Erik Språng242e22b2015-05-11 10:17:43 +0200738
739 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000740}
741
Erik Språng242e22b2015-05-11 10:17:43 +0200742RTCPSender::BuildResult RTCPSender::BuildAPP(RtcpContext* ctx) {
Erik Språng521875a2015-09-01 10:11:16 +0200743 rtcp::App app;
744 app.From(ssrc_);
745 app.WithSubType(app_sub_type_);
746 app.WithName(app_name_);
747 app.WithData(app_data_.get(), app_length_);
748
749 PacketBuiltCallback callback(ctx);
750 if (!callback.BuildPacket(app))
Erik Språng242e22b2015-05-11 10:17:43 +0200751 return BuildResult::kTruncated;
Erik Språng242e22b2015-05-11 10:17:43 +0200752
753 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +0200754}
755
Erik Språng242e22b2015-05-11 10:17:43 +0200756RTCPSender::BuildResult RTCPSender::BuildNACK(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200757 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200758 if (ctx->position + 16 >= IP_PACKET_SIZE) {
Erik Språng61be2a42015-04-27 13:32:52 +0200759 LOG(LS_WARNING) << "Failed to build NACK.";
Erik Språng242e22b2015-05-11 10:17:43 +0200760 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200761 }
762
Erik Språng242e22b2015-05-11 10:17:43 +0200763 // int size, uint16_t* nack_list
Erik Språng61be2a42015-04-27 13:32:52 +0200764 // add nack list
765 uint8_t FMT = 1;
Erik Språng242e22b2015-05-11 10:17:43 +0200766 *ctx->AllocateData(1) = 0x80 + FMT;
767 *ctx->AllocateData(1) = 205;
Erik Språng61be2a42015-04-27 13:32:52 +0200768
Erik Språng242e22b2015-05-11 10:17:43 +0200769 *ctx->AllocateData(1) = 0;
770 int nack_size_pos_ = ctx->position;
771 *ctx->AllocateData(1) = 3; // setting it to one kNACK signal as default
Erik Språng61be2a42015-04-27 13:32:52 +0200772
773 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200774 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200775
776 // Add the remote SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200777 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200778
779 // Build NACK bitmasks and write them to the RTCP message.
780 // The nack list should be sorted and not contain duplicates if one
781 // wants to build the smallest rtcp nack packet.
782 int numOfNackFields = 0;
783 int maxNackFields =
Erik Språng242e22b2015-05-11 10:17:43 +0200784 std::min<int>(kRtcpMaxNackFields, (IP_PACKET_SIZE - ctx->position) / 4);
Erik Språng61be2a42015-04-27 13:32:52 +0200785 int i = 0;
Erik Språng242e22b2015-05-11 10:17:43 +0200786 while (i < ctx->nack_size && numOfNackFields < maxNackFields) {
787 uint16_t nack = ctx->nack_list[i++];
Erik Språng61be2a42015-04-27 13:32:52 +0200788 uint16_t bitmask = 0;
Erik Språng242e22b2015-05-11 10:17:43 +0200789 while (i < ctx->nack_size) {
790 int shift = static_cast<uint16_t>(ctx->nack_list[i] - nack) - 1;
Erik Språng61be2a42015-04-27 13:32:52 +0200791 if (shift >= 0 && shift <= 15) {
792 bitmask |= (1 << shift);
793 ++i;
794 } else {
795 break;
796 }
797 }
798 // Write the sequence number and the bitmask to the packet.
Erik Språng242e22b2015-05-11 10:17:43 +0200799 assert(ctx->position + 4 < IP_PACKET_SIZE);
800 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2), nack);
801 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2), bitmask);
Erik Språng61be2a42015-04-27 13:32:52 +0200802 numOfNackFields++;
803 }
Erik Språng242e22b2015-05-11 10:17:43 +0200804 ctx->buffer[nack_size_pos_] = static_cast<uint8_t>(2 + numOfNackFields);
Erik Språng61be2a42015-04-27 13:32:52 +0200805
Erik Språng242e22b2015-05-11 10:17:43 +0200806 if (i != ctx->nack_size)
Erik Språng61be2a42015-04-27 13:32:52 +0200807 LOG(LS_WARNING) << "Nack list too large for one packet.";
808
809 // Report stats.
810 NACKStringBuilder stringBuilder;
811 for (int idx = 0; idx < i; ++idx) {
Erik Språng242e22b2015-05-11 10:17:43 +0200812 stringBuilder.PushNACK(ctx->nack_list[idx]);
813 nack_stats_.ReportRequest(ctx->nack_list[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +0200814 }
Erik Språng61be2a42015-04-27 13:32:52 +0200815 packet_type_counter_.nack_requests = nack_stats_.requests();
816 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +0200817
818 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
819 "RTCPSender::NACK", "nacks",
820 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
821 ++packet_type_counter_.nack_packets;
822 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
823 ssrc_, packet_type_counter_.nack_packets);
824
825 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +0200826}
827
Erik Språng242e22b2015-05-11 10:17:43 +0200828RTCPSender::BuildResult RTCPSender::BuildBYE(RtcpContext* ctx) {
sprangd8ee4f92015-08-24 03:25:19 -0700829 rtcp::Bye bye;
830 bye.From(ssrc_);
831 for (uint32_t csrc : csrcs_)
832 bye.WithCsrc(csrc);
833
834 PacketBuiltCallback callback(ctx);
835 if (!callback.BuildPacket(bye))
Erik Språng242e22b2015-05-11 10:17:43 +0200836 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000837
Erik Språng242e22b2015-05-11 10:17:43 +0200838 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000839}
840
Erik Språng242e22b2015-05-11 10:17:43 +0200841RTCPSender::BuildResult RTCPSender::BuildReceiverReferenceTime(
842 RtcpContext* ctx) {
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000843
Erik Språng61be2a42015-04-27 13:32:52 +0200844 if (last_xr_rr_.size() >= RTCP_NUMBER_OF_SR)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000845 last_xr_rr_.erase(last_xr_rr_.begin());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000846 last_xr_rr_.insert(std::pair<uint32_t, int64_t>(
Erik Språng242e22b2015-05-11 10:17:43 +0200847 RTCPUtility::MidNtp(ctx->ntp_sec, ctx->ntp_frac),
848 Clock::NtpToMs(ctx->ntp_sec, ctx->ntp_frac)));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000849
Erik Språngca28fdc2015-08-31 14:00:50 +0200850 rtcp::Xr xr;
851 xr.From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000852
Erik Språngca28fdc2015-08-31 14:00:50 +0200853 rtcp::Rrtr rrtr;
854 rrtr.WithNtpSec(ctx->ntp_sec);
855 rrtr.WithNtpFrac(ctx->ntp_frac);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000856
Erik Språngca28fdc2015-08-31 14:00:50 +0200857 xr.WithRrtr(&rrtr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000858
Erik Språngca28fdc2015-08-31 14:00:50 +0200859 // TODO(sprang): Merge XR report sending to contain all of RRTR, DLRR, VOIP?
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000860
Erik Språngca28fdc2015-08-31 14:00:50 +0200861 PacketBuiltCallback callback(ctx);
862 if (!callback.BuildPacket(xr))
863 return BuildResult::kTruncated;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000864
Erik Språng242e22b2015-05-11 10:17:43 +0200865 return BuildResult::kSuccess;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000866}
867
Erik Språng242e22b2015-05-11 10:17:43 +0200868RTCPSender::BuildResult RTCPSender::BuildDlrr(RtcpContext* ctx) {
Erik Språngca28fdc2015-08-31 14:00:50 +0200869 rtcp::Xr xr;
870 xr.From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000871
Erik Språngca28fdc2015-08-31 14:00:50 +0200872 rtcp::Dlrr dlrr;
Erik Språng242e22b2015-05-11 10:17:43 +0200873 const RtcpReceiveTimeInfo& info = ctx->feedback_state.last_xr_rr;
Erik Språngca28fdc2015-08-31 14:00:50 +0200874 dlrr.WithDlrrItem(info.sourceSSRC, info.lastRR, info.delaySinceLastRR);
875
876 xr.WithDlrr(&dlrr);
877
878 PacketBuiltCallback callback(ctx);
879 if (!callback.BuildPacket(xr))
880 return BuildResult::kTruncated;
Erik Språng242e22b2015-05-11 10:17:43 +0200881
882 return BuildResult::kSuccess;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000883}
884
Erik Språng242e22b2015-05-11 10:17:43 +0200885// TODO(sprang): Add a unit test for this, or remove if the code isn't used.
886RTCPSender::BuildResult RTCPSender::BuildVoIPMetric(RtcpContext* ctx) {
Erik Språngca28fdc2015-08-31 14:00:50 +0200887 rtcp::Xr xr;
888 xr.From(ssrc_);
889
890 rtcp::VoipMetric voip;
891 voip.To(remote_ssrc_);
892 voip.LossRate(xr_voip_metric_.lossRate);
893 voip.DiscardRate(xr_voip_metric_.discardRate);
894 voip.BurstDensity(xr_voip_metric_.burstDensity);
895 voip.GapDensity(xr_voip_metric_.gapDensity);
896 voip.BurstDuration(xr_voip_metric_.burstDuration);
897 voip.GapDuration(xr_voip_metric_.gapDuration);
898 voip.RoundTripDelay(xr_voip_metric_.roundTripDelay);
899 voip.EndSystemDelay(xr_voip_metric_.endSystemDelay);
900 voip.SignalLevel(xr_voip_metric_.signalLevel);
901 voip.NoiseLevel(xr_voip_metric_.noiseLevel);
902 voip.Rerl(xr_voip_metric_.RERL);
903 voip.Gmin(xr_voip_metric_.Gmin);
904 voip.Rfactor(xr_voip_metric_.Rfactor);
905 voip.ExtRfactor(xr_voip_metric_.extRfactor);
906 voip.MosLq(xr_voip_metric_.MOSLQ);
907 voip.MosCq(xr_voip_metric_.MOSCQ);
908 voip.RxConfig(xr_voip_metric_.RXconfig);
909 voip.JbNominal(xr_voip_metric_.JBnominal);
910 voip.JbMax(xr_voip_metric_.JBmax);
911 voip.JbAbsMax(xr_voip_metric_.JBabsMax);
912
913 xr.WithVoipMetric(&voip);
914
915 PacketBuiltCallback callback(ctx);
916 if (!callback.BuildPacket(xr))
Erik Språng242e22b2015-05-11 10:17:43 +0200917 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000918
Erik Språng242e22b2015-05-11 10:17:43 +0200919 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000920}
921
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000922int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200923 RTCPPacketType packetType,
924 int32_t nack_size,
925 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000926 bool repeat,
927 uint64_t pictureID) {
Erik Språng242e22b2015-05-11 10:17:43 +0200928 return SendCompoundRTCP(
929 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
930 nack_size, nack_list, repeat, pictureID);
931}
932
933int32_t RTCPSender::SendCompoundRTCP(
934 const FeedbackState& feedback_state,
935 const std::set<RTCPPacketType>& packetTypes,
936 int32_t nack_size,
937 const uint16_t* nack_list,
938 bool repeat,
939 uint64_t pictureID) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000940 {
Erik Språng242e22b2015-05-11 10:17:43 +0200941 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
pbosda903ea2015-10-02 02:36:56 -0700942 if (method_ == RtcpMode::kOff) {
Erik Språng61be2a42015-04-27 13:32:52 +0200943 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
944 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +0000945 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000946 }
947 uint8_t rtcp_buffer[IP_PACKET_SIZE];
Erik Språng242e22b2015-05-11 10:17:43 +0200948 int rtcp_length =
949 PrepareRTCP(feedback_state, packetTypes, nack_size, nack_list, repeat,
950 pictureID, rtcp_buffer, IP_PACKET_SIZE);
Erik Språng61be2a42015-04-27 13:32:52 +0200951
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000952 // Sanity don't send empty packets.
Erik Språng242e22b2015-05-11 10:17:43 +0200953 if (rtcp_length <= 0)
954 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200955
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000956 return SendToNetwork(rtcp_buffer, static_cast<size_t>(rtcp_length));
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000957}
958
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000959int RTCPSender::PrepareRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200960 const std::set<RTCPPacketType>& packetTypes,
961 int32_t nack_size,
962 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000963 bool repeat,
964 uint64_t pictureID,
965 uint8_t* rtcp_buffer,
966 int buffer_size) {
Erik Språng242e22b2015-05-11 10:17:43 +0200967 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000968
Erik Språng242e22b2015-05-11 10:17:43 +0200969 RtcpContext context(feedback_state, nack_size, nack_list, repeat, pictureID,
970 rtcp_buffer, buffer_size);
971
972 // Add all flags as volatile. Non volatile entries will not be overwritten
973 // and all new volatile flags added will be consumed by the end of this call.
974 SetFlags(packetTypes, true);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000975
Erik Språng61be2a42015-04-27 13:32:52 +0200976 if (packet_type_counter_.first_packet_time_ms == -1)
Erik Språng242e22b2015-05-11 10:17:43 +0200977 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språng61be2a42015-04-27 13:32:52 +0200978
Erik Språng242e22b2015-05-11 10:17:43 +0200979 bool generate_report;
980 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
981 // Report type already explicitly set, don't automatically populate.
982 generate_report = true;
henrikg91d6ede2015-09-17 00:24:34 -0700983 RTC_DCHECK(ConsumeFlag(kRtcpReport) == false);
Erik Språng242e22b2015-05-11 10:17:43 +0200984 } else {
985 generate_report =
pbosda903ea2015-10-02 02:36:56 -0700986 (ConsumeFlag(kRtcpReport) && method_ == RtcpMode::kReducedSize) ||
987 method_ == RtcpMode::kCompound;
Erik Språng242e22b2015-05-11 10:17:43 +0200988 if (generate_report)
989 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000990 }
991
Erik Språng0ea42d32015-06-25 14:46:16 +0200992 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
Erik Språng242e22b2015-05-11 10:17:43 +0200993 SetFlag(kRtcpSdes, true);
994
995 // We need to send our NTP even if we haven't received any reports.
996 clock_->CurrentNtp(context.ntp_sec, context.ntp_frac);
997
998 if (generate_report) {
999 if (!sending_ && xr_send_receiver_reference_time_enabled_)
1000 SetFlag(kRtcpXrReceiverReferenceTime, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001001 if (feedback_state.has_last_xr_rr)
Erik Språng242e22b2015-05-11 10:17:43 +02001002 SetFlag(kRtcpXrDlrrReportBlock, true);
1003
1004 // generate next time to send an RTCP report
Erik Språng61be2a42015-04-27 13:32:52 +02001005 // seeded from RTP constructor
1006 int32_t random = rand() % 1000;
1007 int32_t timeToNext = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001008
Erik Språng242e22b2015-05-11 10:17:43 +02001009 if (audio_) {
Erik Språng61be2a42015-04-27 13:32:52 +02001010 timeToNext = (RTCP_INTERVAL_AUDIO_MS / 2) +
1011 (RTCP_INTERVAL_AUDIO_MS * random / 1000);
1012 } else {
1013 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
Erik Språng242e22b2015-05-11 10:17:43 +02001014 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +02001015 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
1016 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
1017 if (send_bitrate_kbit != 0)
1018 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001019 }
Erik Språng61be2a42015-04-27 13:32:52 +02001020 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
1021 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
1022 timeToNext = (minIntervalMs / 2) + (minIntervalMs * random / 1000);
1023 }
Erik Språng242e22b2015-05-11 10:17:43 +02001024 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001025
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001026 StatisticianMap statisticians =
1027 receive_statistics_->GetActiveStatisticians();
1028 if (!statisticians.empty()) {
Erik Språng61be2a42015-04-27 13:32:52 +02001029 for (auto it = statisticians.begin(); it != statisticians.end(); ++it) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001030 RTCPReportBlock report_block;
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001031 if (PrepareReport(feedback_state, it->first, it->second,
1032 &report_block)) {
danilchapdf948f02015-11-13 03:03:13 -08001033 // TODO(danilchap) AddReportBlock may fail (for 2 different reasons).
1034 // Probably it shouldn't be ignored.
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001035 AddReportBlock(report_block);
Erik Språng61be2a42015-04-27 13:32:52 +02001036 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001037 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001038 }
1039 }
1040
Erik Språng242e22b2015-05-11 10:17:43 +02001041 auto it = report_flags_.begin();
1042 while (it != report_flags_.end()) {
1043 auto builder = builders_.find(it->type);
henrikg91d6ede2015-09-17 00:24:34 -07001044 RTC_DCHECK(builder != builders_.end());
Erik Språng242e22b2015-05-11 10:17:43 +02001045 if (it->is_volatile) {
1046 report_flags_.erase(it++);
1047 } else {
1048 ++it;
Erik Språng61be2a42015-04-27 13:32:52 +02001049 }
Erik Språng242e22b2015-05-11 10:17:43 +02001050
1051 uint32_t start_position = context.position;
Erik Språng0ea42d32015-06-25 14:46:16 +02001052 BuildResult result = (this->*(builder->second))(&context);
Erik Språng242e22b2015-05-11 10:17:43 +02001053 switch (result) {
1054 case BuildResult::kError:
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001055 return -1;
Erik Språng242e22b2015-05-11 10:17:43 +02001056 case BuildResult::kTruncated:
1057 return context.position;
1058 case BuildResult::kAborted:
1059 context.position = start_position;
1060 FALLTHROUGH();
1061 case BuildResult::kSuccess:
1062 continue;
Erik Språng61be2a42015-04-27 13:32:52 +02001063 default:
Erik Språng242e22b2015-05-11 10:17:43 +02001064 abort();
Erik Språng61be2a42015-04-27 13:32:52 +02001065 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001066 }
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001067
1068 if (packet_type_counter_observer_ != NULL) {
1069 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
Erik Språng242e22b2015-05-11 10:17:43 +02001070 remote_ssrc_, packet_type_counter_);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001071 }
1072
henrikg91d6ede2015-09-17 00:24:34 -07001073 RTC_DCHECK(AllVolatileFlagsConsumed());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001074
Erik Språng242e22b2015-05-11 10:17:43 +02001075 return context.position;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001076}
1077
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001078bool RTCPSender::PrepareReport(const FeedbackState& feedback_state,
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001079 uint32_t ssrc,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001080 StreamStatistician* statistician,
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001081 RTCPReportBlock* report_block) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001082 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +00001083 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001084 if (!statistician->GetStatistics(&stats, true))
1085 return false;
1086 report_block->fractionLost = stats.fraction_lost;
1087 report_block->cumulativeLost = stats.cumulative_lost;
1088 report_block->extendedHighSeqNum =
1089 stats.extended_max_sequence_number;
1090 report_block->jitter = stats.jitter;
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001091 report_block->remoteSSRC = ssrc;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001092
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001093 // TODO(sprang): Do we really need separate time stamps for each report?
1094 // Get our NTP as late as possible to avoid a race.
1095 uint32_t ntp_secs;
1096 uint32_t ntp_frac;
1097 clock_->CurrentNtp(ntp_secs, ntp_frac);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001098
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001099 // Delay since last received report.
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001100 uint32_t delaySinceLastReceivedSR = 0;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001101 if ((feedback_state.last_rr_ntp_secs != 0) ||
1102 (feedback_state.last_rr_ntp_frac != 0)) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001103 // Get the 16 lowest bits of seconds and the 16 highest bits of fractions.
1104 uint32_t now = ntp_secs & 0x0000FFFF;
Erik Språng61be2a42015-04-27 13:32:52 +02001105 now <<= 16;
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001106 now += (ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001107
Erik Språng61be2a42015-04-27 13:32:52 +02001108 uint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
1109 receiveTime <<= 16;
1110 receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001111
1112 delaySinceLastReceivedSR = now-receiveTime;
1113 }
1114 report_block->delaySinceLastSR = delaySinceLastReceivedSR;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001115 report_block->lastSR = feedback_state.remote_sr;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001116 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +00001117}
1118
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001119int32_t RTCPSender::SendToNetwork(const uint8_t* dataBuffer, size_t length) {
sprang86fd9ed2015-09-29 04:45:43 -07001120 if (transport_->SendRtcp(dataBuffer, length))
1121 return 0;
Erik Språng61be2a42015-04-27 13:32:52 +02001122 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001123}
1124
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001125void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
1126 assert(csrcs.size() <= kRtpCsrcSize);
Erik Språng242e22b2015-05-11 10:17:43 +02001127 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001128 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +00001129}
1130
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001131int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
1132 uint32_t name,
1133 const uint8_t* data,
1134 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +02001135 if (length % 4 != 0) {
1136 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
1137 return -1;
1138 }
Erik Språng242e22b2015-05-11 10:17:43 +02001139 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +00001140
Erik Språng242e22b2015-05-11 10:17:43 +02001141 SetFlag(kRtcpApp, true);
1142 app_sub_type_ = subType;
1143 app_name_ = name;
1144 app_data_.reset(new uint8_t[length]);
1145 app_length_ = length;
1146 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +02001147 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001148}
1149
Erik Språng61be2a42015-04-27 13:32:52 +02001150int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
Erik Språng242e22b2015-05-11 10:17:43 +02001151 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1152 memcpy(&xr_voip_metric_, VoIPMetric, sizeof(RTCPVoIPMetric));
niklase@google.com470e71d2011-07-07 08:21:25 +00001153
Erik Språng242e22b2015-05-11 10:17:43 +02001154 SetFlag(kRtcpXrVoipMetric, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001155 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001156}
1157
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001158void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +02001159 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1160 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001161}
1162
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00001163bool RTCPSender::RtcpXrReceiverReferenceTime() const {
Erik Språng242e22b2015-05-11 10:17:43 +02001164 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1165 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00001166}
1167
niklase@google.com470e71d2011-07-07 08:21:25 +00001168// no callbacks allowed inside this function
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001169int32_t RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
1170 uint32_t maxBitrateKbit) {
Erik Språng242e22b2015-05-11 10:17:43 +02001171 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +00001172
Erik Språng242e22b2015-05-11 10:17:43 +02001173 if (0 == tmmbr_help_.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit)) {
1174 SetFlag(kRtcpTmmbn, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001175 return 0;
1176 }
1177 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001178}
Erik Språng61be2a42015-04-27 13:32:52 +02001179
Erik Språng242e22b2015-05-11 10:17:43 +02001180void RTCPSender::SetFlag(RTCPPacketType type, bool is_volatile) {
1181 report_flags_.insert(ReportFlag(type, is_volatile));
1182}
1183
1184void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
1185 bool is_volatile) {
1186 for (RTCPPacketType type : types)
1187 SetFlag(type, is_volatile);
1188}
1189
1190bool RTCPSender::IsFlagPresent(RTCPPacketType type) const {
1191 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
1192}
1193
1194bool RTCPSender::ConsumeFlag(RTCPPacketType type, bool forced) {
1195 auto it = report_flags_.find(ReportFlag(type, false));
1196 if (it == report_flags_.end())
1197 return false;
1198 if (it->is_volatile || forced)
1199 report_flags_.erase((it));
1200 return true;
1201}
1202
1203bool RTCPSender::AllVolatileFlagsConsumed() const {
1204 for (const ReportFlag& flag : report_flags_) {
1205 if (flag.is_volatile)
1206 return false;
1207 }
1208 return true;
1209}
1210
sprang233bd872015-09-08 13:25:16 -07001211bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
sprang233bd872015-09-08 13:25:16 -07001212 class Sender : public rtcp::RtcpPacket::PacketReadyCallback {
1213 public:
Peter Boströmac547a62015-09-17 23:03:57 +02001214 Sender(Transport* transport)
1215 : transport_(transport), send_failure_(false) {}
sprang233bd872015-09-08 13:25:16 -07001216
1217 void OnPacketReady(uint8_t* data, size_t length) override {
pbos2d566682015-09-28 09:59:31 -07001218 if (!transport_->SendRtcp(data, length))
sprang233bd872015-09-08 13:25:16 -07001219 send_failure_ = true;
1220 }
1221
1222 Transport* const transport_;
sprang233bd872015-09-08 13:25:16 -07001223 bool send_failure_;
sprang86fd9ed2015-09-29 04:45:43 -07001224 } sender(transport_);
sprang233bd872015-09-08 13:25:16 -07001225
1226 uint8_t buffer[IP_PACKET_SIZE];
1227 return packet.BuildExternalBuffer(buffer, IP_PACKET_SIZE, &sender) &&
1228 !sender.send_failure_;
1229}
1230
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001231} // namespace webrtc