blob: 111757b7afcb682a25a1e5cb8c4261bf38ebede4 [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"
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000021#include "webrtc/common_types.h"
sprang@webrtc.org779c3d12015-03-17 16:42:49 +000022#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000023#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
sprang233bd872015-09-08 13:25:16 -070024#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000025#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +000026#include "webrtc/system_wrappers/interface/logging.h"
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000027#include "webrtc/system_wrappers/interface/trace_event.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000028
niklase@google.com470e71d2011-07-07 08:21:25 +000029namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000030
31using RTCPUtility::RTCPCnameInformation;
32
Erik Språng61be2a42015-04-27 13:32:52 +020033NACKStringBuilder::NACKStringBuilder()
Erik Språng242e22b2015-05-11 10:17:43 +020034 : stream_(""), count_(0), prevNack_(0), consecutive_(false) {
edjee@google.com79b02892013-04-04 19:43:34 +000035}
36
pbos@webrtc.orgf3e4cee2013-07-31 15:17:19 +000037NACKStringBuilder::~NACKStringBuilder() {}
38
pbos@webrtc.org2f446732013-04-08 11:08:41 +000039void NACKStringBuilder::PushNACK(uint16_t nack)
edjee@google.com79b02892013-04-04 19:43:34 +000040{
Erik Språng242e22b2015-05-11 10:17:43 +020041 if (count_ == 0) {
42 stream_ << nack;
43 } else if (nack == prevNack_ + 1) {
44 consecutive_ = true;
Erik Språng61be2a42015-04-27 13:32:52 +020045 } else {
Erik Språng242e22b2015-05-11 10:17:43 +020046 if (consecutive_) {
47 stream_ << "-" << prevNack_;
48 consecutive_ = false;
edjee@google.com79b02892013-04-04 19:43:34 +000049 }
Erik Språng242e22b2015-05-11 10:17:43 +020050 stream_ << "," << nack;
Erik Språng61be2a42015-04-27 13:32:52 +020051 }
Erik Språng242e22b2015-05-11 10:17:43 +020052 count_++;
53 prevNack_ = nack;
edjee@google.com79b02892013-04-04 19:43:34 +000054}
55
Erik Språng61be2a42015-04-27 13:32:52 +020056std::string NACKStringBuilder::GetResult() {
Erik Språng242e22b2015-05-11 10:17:43 +020057 if (consecutive_) {
58 stream_ << "-" << prevNack_;
59 consecutive_ = false;
Erik Språng61be2a42015-04-27 13:32:52 +020060 }
Erik Språng242e22b2015-05-11 10:17:43 +020061 return stream_.str();
edjee@google.com79b02892013-04-04 19:43:34 +000062}
63
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000064RTCPSender::FeedbackState::FeedbackState()
65 : send_payload_type(0),
66 frequency_hz(0),
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +000067 packets_sent(0),
68 media_bytes_sent(0),
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000069 send_bitrate(0),
70 last_rr_ntp_secs(0),
71 last_rr_ntp_frac(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000072 remote_sr(0),
Erik Språng61be2a42015-04-27 13:32:52 +020073 has_last_xr_rr(false),
74 module(nullptr) {
75}
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000076
Erik Språng242e22b2015-05-11 10:17:43 +020077struct RTCPSender::RtcpContext {
78 RtcpContext(const FeedbackState& feedback_state,
79 int32_t nack_size,
80 const uint16_t* nack_list,
81 bool repeat,
82 uint64_t picture_id,
83 uint8_t* buffer,
84 uint32_t buffer_size)
85 : feedback_state(feedback_state),
86 nack_size(nack_size),
87 nack_list(nack_list),
88 repeat(repeat),
89 picture_id(picture_id),
90 buffer(buffer),
91 buffer_size(buffer_size),
92 ntp_sec(0),
93 ntp_frac(0),
Erik Språng242e22b2015-05-11 10:17:43 +020094 position(0) {}
95
96 uint8_t* AllocateData(uint32_t bytes) {
henrikg91d6ede2015-09-17 00:24:34 -070097 RTC_DCHECK_LE(position + bytes, buffer_size);
Erik Språng242e22b2015-05-11 10:17:43 +020098 uint8_t* ptr = &buffer[position];
99 position += bytes;
100 return ptr;
101 }
102
103 const FeedbackState& feedback_state;
104 int32_t nack_size;
105 const uint16_t* nack_list;
106 bool repeat;
107 uint64_t picture_id;
108 uint8_t* buffer;
109 uint32_t buffer_size;
110 uint32_t ntp_sec;
111 uint32_t ntp_frac;
Erik Språng242e22b2015-05-11 10:17:43 +0200112 uint32_t position;
113};
114
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200115// TODO(sprang): Once all builders use RtcpPacket, call SendToNetwork() here.
116class RTCPSender::PacketBuiltCallback
117 : public rtcp::RtcpPacket::PacketReadyCallback {
118 public:
119 PacketBuiltCallback(RtcpContext* context) : context_(context) {}
120 virtual ~PacketBuiltCallback() {}
121 void OnPacketReady(uint8_t* data, size_t length) override {
122 context_->position += length;
123 }
Erik Språng72aa9a62015-07-31 16:16:02 +0200124 bool BuildPacket(const rtcp::RtcpPacket& packet) {
125 return packet.BuildExternalBuffer(
126 &context_->buffer[context_->position],
127 context_->buffer_size - context_->position, this);
128 }
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200129
130 private:
131 RtcpContext* const context_;
132};
133
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000134RTCPSender::RTCPSender(
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000135 bool audio,
136 Clock* clock,
137 ReceiveStatistics* receive_statistics,
138 RtcpPacketTypeCounterObserver* packet_type_counter_observer)
Peter Boströmac547a62015-09-17 23:03:57 +0200139 : audio_(audio),
Erik Språng242e22b2015-05-11 10:17:43 +0200140 clock_(clock),
141 method_(kRtcpOff),
142 critical_section_transport_(
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000143 CriticalSectionWrapper::CreateCriticalSection()),
Erik Språng242e22b2015-05-11 10:17:43 +0200144 cbTransport_(nullptr),
niklase@google.com470e71d2011-07-07 08:21:25 +0000145
Erik Språng242e22b2015-05-11 10:17:43 +0200146 critical_section_rtcp_sender_(
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000147 CriticalSectionWrapper::CreateCriticalSection()),
Erik Språng242e22b2015-05-11 10:17:43 +0200148 using_nack_(false),
149 sending_(false),
150 remb_enabled_(false),
Erik Språng242e22b2015-05-11 10:17:43 +0200151 next_time_to_send_rtcp_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000152 start_timestamp_(0),
153 last_rtp_timestamp_(0),
154 last_frame_capture_time_ms_(-1),
Erik Språng242e22b2015-05-11 10:17:43 +0200155 ssrc_(0),
156 remote_ssrc_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000157 receive_statistics_(receive_statistics),
niklase@google.com470e71d2011-07-07 08:21:25 +0000158
Erik Språng242e22b2015-05-11 10:17:43 +0200159 sequence_number_fir_(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000160
Erik Språng242e22b2015-05-11 10:17:43 +0200161 remb_bitrate_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000162
Erik Språng242e22b2015-05-11 10:17:43 +0200163 tmmbr_help_(),
164 tmmbr_send_(0),
165 packet_oh_send_(0),
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000166
Erik Språng242e22b2015-05-11 10:17:43 +0200167 app_sub_type_(0),
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200168 app_name_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200169 app_data_(nullptr),
170 app_length_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000171
Erik Språng242e22b2015-05-11 10:17:43 +0200172 xr_send_receiver_reference_time_enabled_(false),
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000173 packet_type_counter_observer_(packet_type_counter_observer) {
Erik Språng242e22b2015-05-11 10:17:43 +0200174 memset(last_send_report_, 0, sizeof(last_send_report_));
175 memset(last_rtcp_time_, 0, sizeof(last_rtcp_time_));
176
177 builders_[kRtcpSr] = &RTCPSender::BuildSR;
178 builders_[kRtcpRr] = &RTCPSender::BuildRR;
Erik Språng0ea42d32015-06-25 14:46:16 +0200179 builders_[kRtcpSdes] = &RTCPSender::BuildSDES;
Erik Språng242e22b2015-05-11 10:17:43 +0200180 builders_[kRtcpPli] = &RTCPSender::BuildPLI;
181 builders_[kRtcpFir] = &RTCPSender::BuildFIR;
182 builders_[kRtcpSli] = &RTCPSender::BuildSLI;
183 builders_[kRtcpRpsi] = &RTCPSender::BuildRPSI;
184 builders_[kRtcpRemb] = &RTCPSender::BuildREMB;
185 builders_[kRtcpBye] = &RTCPSender::BuildBYE;
186 builders_[kRtcpApp] = &RTCPSender::BuildAPP;
187 builders_[kRtcpTmmbr] = &RTCPSender::BuildTMMBR;
188 builders_[kRtcpTmmbn] = &RTCPSender::BuildTMMBN;
189 builders_[kRtcpNack] = &RTCPSender::BuildNACK;
190 builders_[kRtcpXrVoipMetric] = &RTCPSender::BuildVoIPMetric;
191 builders_[kRtcpXrReceiverReferenceTime] =
192 &RTCPSender::BuildReceiverReferenceTime;
193 builders_[kRtcpXrDlrrReportBlock] = &RTCPSender::BuildDlrr;
niklase@google.com470e71d2011-07-07 08:21:25 +0000194}
195
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000196RTCPSender::~RTCPSender() {
niklase@google.com470e71d2011-07-07 08:21:25 +0000197}
198
Erik Språng61be2a42015-04-27 13:32:52 +0200199int32_t RTCPSender::RegisterSendTransport(Transport* outgoingTransport) {
Erik Språng242e22b2015-05-11 10:17:43 +0200200 CriticalSectionScoped lock(critical_section_transport_.get());
201 cbTransport_ = outgoingTransport;
Erik Språng61be2a42015-04-27 13:32:52 +0200202 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000203}
204
Erik Språng61be2a42015-04-27 13:32:52 +0200205RTCPMethod RTCPSender::Status() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200206 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
207 return method_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000208}
209
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000210void RTCPSender::SetRTCPStatus(RTCPMethod method) {
Erik Språng242e22b2015-05-11 10:17:43 +0200211 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
212 method_ = method;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000213
214 if (method == kRtcpOff)
215 return;
Erik Språng242e22b2015-05-11 10:17:43 +0200216 next_time_to_send_rtcp_ =
217 clock_->TimeInMilliseconds() +
218 (audio_ ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000219}
220
Erik Språng61be2a42015-04-27 13:32:52 +0200221bool RTCPSender::Sending() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200222 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
223 return sending_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000224}
225
Erik Språng61be2a42015-04-27 13:32:52 +0200226int32_t RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
227 bool sending) {
228 bool sendRTCPBye = false;
229 {
Erik Språng242e22b2015-05-11 10:17:43 +0200230 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000231
Erik Språng242e22b2015-05-11 10:17:43 +0200232 if (method_ != kRtcpOff) {
233 if (sending == false && sending_ == true) {
Erik Språng61be2a42015-04-27 13:32:52 +0200234 // Trigger RTCP bye
235 sendRTCPBye = true;
236 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000237 }
Erik Språng242e22b2015-05-11 10:17:43 +0200238 sending_ = sending;
Erik Språng61be2a42015-04-27 13:32:52 +0200239 }
240 if (sendRTCPBye)
241 return SendRTCP(feedback_state, kRtcpBye);
242 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000243}
244
Erik Språng61be2a42015-04-27 13:32:52 +0200245bool RTCPSender::REMB() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200246 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
247 return remb_enabled_;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000248}
249
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000250void RTCPSender::SetREMBStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200251 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
252 remb_enabled_ = enable;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000253}
254
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000255void RTCPSender::SetREMBData(uint32_t bitrate,
256 const std::vector<uint32_t>& ssrcs) {
Erik Språng242e22b2015-05-11 10:17:43 +0200257 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
258 remb_bitrate_ = bitrate;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000259 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000260
Erik Språng242e22b2015-05-11 10:17:43 +0200261 if (remb_enabled_)
262 SetFlag(kRtcpRemb, false);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000263 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
264 // throttled by the caller.
Erik Språng242e22b2015-05-11 10:17:43 +0200265 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000266}
267
Erik Språng61be2a42015-04-27 13:32:52 +0200268bool RTCPSender::TMMBR() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200269 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
270 return IsFlagPresent(RTCPPacketType::kRtcpTmmbr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000271}
272
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000273void RTCPSender::SetTMMBRStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200274 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
275 if (enable) {
276 SetFlag(RTCPPacketType::kRtcpTmmbr, false);
277 } else {
278 ConsumeFlag(RTCPPacketType::kRtcpTmmbr, true);
279 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000280}
281
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000282void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
Erik Språng242e22b2015-05-11 10:17:43 +0200283 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000284 start_timestamp_ = start_timestamp;
285}
286
287void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
288 int64_t capture_time_ms) {
Erik Språng242e22b2015-05-11 10:17:43 +0200289 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000290 last_rtp_timestamp_ = rtp_timestamp;
291 if (capture_time_ms < 0) {
292 // We don't currently get a capture time from VoiceEngine.
Erik Språng242e22b2015-05-11 10:17:43 +0200293 last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000294 } else {
295 last_frame_capture_time_ms_ = capture_time_ms;
296 }
297}
298
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000299void RTCPSender::SetSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200300 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000301
Erik Språng242e22b2015-05-11 10:17:43 +0200302 if (ssrc_ != 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200303 // not first SetSSRC, probably due to a collision
304 // schedule a new RTCP report
305 // make sure that we send a RTP packet
Erik Språng242e22b2015-05-11 10:17:43 +0200306 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
Erik Språng61be2a42015-04-27 13:32:52 +0200307 }
Erik Språng242e22b2015-05-11 10:17:43 +0200308 ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000309}
310
Erik Språng61be2a42015-04-27 13:32:52 +0200311void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200312 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
313 remote_ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000314}
315
Peter Boström9ba52f82015-06-01 14:12:28 +0200316int32_t RTCPSender::SetCNAME(const char* c_name) {
317 if (!c_name)
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000318 return -1;
319
henrikg91d6ede2015-09-17 00:24:34 -0700320 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
Erik Språng242e22b2015-05-11 10:17:43 +0200321 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200322 cname_ = c_name;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000323 return 0;
324}
325
Erik Språng0ea42d32015-06-25 14:46:16 +0200326int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC, const char* c_name) {
327 assert(c_name);
henrikg91d6ede2015-09-17 00:24:34 -0700328 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
Erik Språng242e22b2015-05-11 10:17:43 +0200329 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200330 if (csrc_cnames_.size() >= kRtpCsrcSize)
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000331 return -1;
Erik Språng0ea42d32015-06-25 14:46:16 +0200332
333 csrc_cnames_[SSRC] = c_name;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000334 return 0;
335}
336
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000337int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
Erik Språng242e22b2015-05-11 10:17:43 +0200338 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200339 auto it = csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000340
Erik Språng242e22b2015-05-11 10:17:43 +0200341 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000342 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200343
Erik Språng242e22b2015-05-11 10:17:43 +0200344 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000345 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000346}
347
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000348bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
niklase@google.com470e71d2011-07-07 08:21:25 +0000349/*
350 For audio we use a fix 5 sec interval
351
352 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000353 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
354 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000355
356
357From RFC 3550
358
359 MAX RTCP BW is 5% if the session BW
360 A send report is approximately 65 bytes inc CNAME
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000361 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000362
363 The RECOMMENDED value for the reduced minimum in seconds is 360
364 divided by the session bandwidth in kilobits/second. This minimum
365 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
366
367 If the participant has not yet sent an RTCP packet (the variable
368 initial is true), the constant Tmin is set to 2.5 seconds, else it
369 is set to 5 seconds.
370
371 The interval between RTCP packets is varied randomly over the
372 range [0.5,1.5] times the calculated interval to avoid unintended
373 synchronization of all participants
374
375 if we send
376 If the participant is a sender (we_sent true), the constant C is
377 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
378 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
379 number of senders.
380
381 if we receive only
382 If we_sent is not true, the constant C is set
383 to the average RTCP packet size divided by 75% of the RTCP
384 bandwidth. The constant n is set to the number of receivers
385 (members - senders). If the number of senders is greater than
386 25%, senders and receivers are treated together.
387
388 reconsideration NOT required for peer-to-peer
389 "timer reconsideration" is
390 employed. This algorithm implements a simple back-off mechanism
391 which causes users to hold back RTCP packet transmission if the
392 group sizes are increasing.
393
394 n = number of members
395 C = avg_size/(rtcpBW/4)
396
397 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
398
399 4. The calculated interval T is set to a number uniformly distributed
400 between 0.5 and 1.5 times the deterministic calculated interval.
401
402 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
403 for the fact that the timer reconsideration algorithm converges to
404 a value of the RTCP bandwidth below the intended average
405*/
406
Erik Språng242e22b2015-05-11 10:17:43 +0200407 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000408
Erik Språng242e22b2015-05-11 10:17:43 +0200409 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
xians@webrtc.org8738d272011-11-25 13:43:53 +0000410
Erik Språng242e22b2015-05-11 10:17:43 +0200411 if (method_ == kRtcpOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000412 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000413
Erik Språng242e22b2015-05-11 10:17:43 +0200414 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200415 // for video key-frames we want to send the RTCP before the large key-frame
416 // if we have a 100 ms margin
417 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
418 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000419
Erik Språng242e22b2015-05-11 10:17:43 +0200420 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200421 return true;
422 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200423 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200424 // wrap
425 return true;
426 }
427 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000428}
429
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000430int64_t RTCPSender::SendTimeOfSendReport(uint32_t sendReport) {
Erik Språng242e22b2015-05-11 10:17:43 +0200431 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000432
Erik Språng61be2a42015-04-27 13:32:52 +0200433 // This is only saved when we are the sender
Erik Språng242e22b2015-05-11 10:17:43 +0200434 if ((last_send_report_[0] == 0) || (sendReport == 0)) {
Erik Språng61be2a42015-04-27 13:32:52 +0200435 return 0; // will be ignored
436 } else {
437 for (int i = 0; i < RTCP_NUMBER_OF_SR; ++i) {
Erik Språng242e22b2015-05-11 10:17:43 +0200438 if (last_send_report_[i] == sendReport)
439 return last_rtcp_time_[i];
niklase@google.com470e71d2011-07-07 08:21:25 +0000440 }
Erik Språng61be2a42015-04-27 13:32:52 +0200441 }
442 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000443}
444
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000445bool RTCPSender::SendTimeOfXrRrReport(uint32_t mid_ntp,
446 int64_t* time_ms) const {
Erik Språng242e22b2015-05-11 10:17:43 +0200447 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000448
449 if (last_xr_rr_.empty()) {
450 return false;
451 }
452 std::map<uint32_t, int64_t>::const_iterator it = last_xr_rr_.find(mid_ntp);
453 if (it == last_xr_rr_.end()) {
454 return false;
455 }
456 *time_ms = it->second;
457 return true;
458}
459
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200460int32_t RTCPSender::AddReportBlock(const RTCPReportBlock& report_block) {
461 if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000462 LOG(LS_WARNING) << "Too many report blocks.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000463 return -1;
464 }
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200465 rtcp::ReportBlock* block = &report_blocks_[report_block.remoteSSRC];
466 block->To(report_block.remoteSSRC);
467 block->WithFractionLost(report_block.fractionLost);
468 block->WithCumulativeLost(report_block.cumulativeLost);
469 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());
942 if (method_ == kRtcpOff) {
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 =
986 (ConsumeFlag(kRtcpReport) && method_ == kRtcpNonCompound) ||
987 method_ == kRtcpCompound;
988 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)) {
1033 AddReportBlock(report_block);
Erik Språng61be2a42015-04-27 13:32:52 +02001034 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001035 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001036 }
1037 }
1038
Erik Språng242e22b2015-05-11 10:17:43 +02001039 auto it = report_flags_.begin();
1040 while (it != report_flags_.end()) {
1041 auto builder = builders_.find(it->type);
henrikg91d6ede2015-09-17 00:24:34 -07001042 RTC_DCHECK(builder != builders_.end());
Erik Språng242e22b2015-05-11 10:17:43 +02001043 if (it->is_volatile) {
1044 report_flags_.erase(it++);
1045 } else {
1046 ++it;
Erik Språng61be2a42015-04-27 13:32:52 +02001047 }
Erik Språng242e22b2015-05-11 10:17:43 +02001048
1049 uint32_t start_position = context.position;
Erik Språng0ea42d32015-06-25 14:46:16 +02001050 BuildResult result = (this->*(builder->second))(&context);
Erik Språng242e22b2015-05-11 10:17:43 +02001051 switch (result) {
1052 case BuildResult::kError:
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001053 return -1;
Erik Språng242e22b2015-05-11 10:17:43 +02001054 case BuildResult::kTruncated:
1055 return context.position;
1056 case BuildResult::kAborted:
1057 context.position = start_position;
1058 FALLTHROUGH();
1059 case BuildResult::kSuccess:
1060 continue;
Erik Språng61be2a42015-04-27 13:32:52 +02001061 default:
Erik Språng242e22b2015-05-11 10:17:43 +02001062 abort();
Erik Språng61be2a42015-04-27 13:32:52 +02001063 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001064 }
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001065
1066 if (packet_type_counter_observer_ != NULL) {
1067 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
Erik Språng242e22b2015-05-11 10:17:43 +02001068 remote_ssrc_, packet_type_counter_);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001069 }
1070
henrikg91d6ede2015-09-17 00:24:34 -07001071 RTC_DCHECK(AllVolatileFlagsConsumed());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001072
Erik Språng242e22b2015-05-11 10:17:43 +02001073 return context.position;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001074}
1075
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001076bool RTCPSender::PrepareReport(const FeedbackState& feedback_state,
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001077 uint32_t ssrc,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001078 StreamStatistician* statistician,
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001079 RTCPReportBlock* report_block) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001080 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +00001081 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001082 if (!statistician->GetStatistics(&stats, true))
1083 return false;
1084 report_block->fractionLost = stats.fraction_lost;
1085 report_block->cumulativeLost = stats.cumulative_lost;
1086 report_block->extendedHighSeqNum =
1087 stats.extended_max_sequence_number;
1088 report_block->jitter = stats.jitter;
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001089 report_block->remoteSSRC = ssrc;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001090
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001091 // TODO(sprang): Do we really need separate time stamps for each report?
1092 // Get our NTP as late as possible to avoid a race.
1093 uint32_t ntp_secs;
1094 uint32_t ntp_frac;
1095 clock_->CurrentNtp(ntp_secs, ntp_frac);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001096
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001097 // Delay since last received report.
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001098 uint32_t delaySinceLastReceivedSR = 0;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001099 if ((feedback_state.last_rr_ntp_secs != 0) ||
1100 (feedback_state.last_rr_ntp_frac != 0)) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001101 // Get the 16 lowest bits of seconds and the 16 highest bits of fractions.
1102 uint32_t now = ntp_secs & 0x0000FFFF;
Erik Språng61be2a42015-04-27 13:32:52 +02001103 now <<= 16;
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001104 now += (ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001105
Erik Språng61be2a42015-04-27 13:32:52 +02001106 uint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
1107 receiveTime <<= 16;
1108 receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001109
1110 delaySinceLastReceivedSR = now-receiveTime;
1111 }
1112 report_block->delaySinceLastSR = delaySinceLastReceivedSR;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001113 report_block->lastSR = feedback_state.remote_sr;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001114 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +00001115}
1116
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001117int32_t RTCPSender::SendToNetwork(const uint8_t* dataBuffer, size_t length) {
Erik Språng242e22b2015-05-11 10:17:43 +02001118 CriticalSectionScoped lock(critical_section_transport_.get());
1119 if (cbTransport_) {
pbos2d566682015-09-28 09:59:31 -07001120 if (cbTransport_->SendRtcp(dataBuffer, length))
Erik Språng61be2a42015-04-27 13:32:52 +02001121 return 0;
1122 }
1123 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001124}
1125
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001126void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
1127 assert(csrcs.size() <= kRtpCsrcSize);
Erik Språng242e22b2015-05-11 10:17:43 +02001128 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001129 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +00001130}
1131
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001132int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
1133 uint32_t name,
1134 const uint8_t* data,
1135 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +02001136 if (length % 4 != 0) {
1137 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
1138 return -1;
1139 }
Erik Språng242e22b2015-05-11 10:17:43 +02001140 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +00001141
Erik Språng242e22b2015-05-11 10:17:43 +02001142 SetFlag(kRtcpApp, true);
1143 app_sub_type_ = subType;
1144 app_name_ = name;
1145 app_data_.reset(new uint8_t[length]);
1146 app_length_ = length;
1147 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +02001148 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001149}
1150
Erik Språng61be2a42015-04-27 13:32:52 +02001151int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
Erik Språng242e22b2015-05-11 10:17:43 +02001152 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1153 memcpy(&xr_voip_metric_, VoIPMetric, sizeof(RTCPVoIPMetric));
niklase@google.com470e71d2011-07-07 08:21:25 +00001154
Erik Språng242e22b2015-05-11 10:17:43 +02001155 SetFlag(kRtcpXrVoipMetric, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001156 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001157}
1158
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001159void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +02001160 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1161 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001162}
1163
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00001164bool RTCPSender::RtcpXrReceiverReferenceTime() const {
Erik Språng242e22b2015-05-11 10:17:43 +02001165 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1166 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00001167}
1168
niklase@google.com470e71d2011-07-07 08:21:25 +00001169// no callbacks allowed inside this function
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001170int32_t RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
1171 uint32_t maxBitrateKbit) {
Erik Språng242e22b2015-05-11 10:17:43 +02001172 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +00001173
Erik Språng242e22b2015-05-11 10:17:43 +02001174 if (0 == tmmbr_help_.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit)) {
1175 SetFlag(kRtcpTmmbn, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001176 return 0;
1177 }
1178 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001179}
Erik Språng61be2a42015-04-27 13:32:52 +02001180
Erik Språng242e22b2015-05-11 10:17:43 +02001181void RTCPSender::SetFlag(RTCPPacketType type, bool is_volatile) {
1182 report_flags_.insert(ReportFlag(type, is_volatile));
1183}
1184
1185void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
1186 bool is_volatile) {
1187 for (RTCPPacketType type : types)
1188 SetFlag(type, is_volatile);
1189}
1190
1191bool RTCPSender::IsFlagPresent(RTCPPacketType type) const {
1192 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
1193}
1194
1195bool RTCPSender::ConsumeFlag(RTCPPacketType type, bool forced) {
1196 auto it = report_flags_.find(ReportFlag(type, false));
1197 if (it == report_flags_.end())
1198 return false;
1199 if (it->is_volatile || forced)
1200 report_flags_.erase((it));
1201 return true;
1202}
1203
1204bool RTCPSender::AllVolatileFlagsConsumed() const {
1205 for (const ReportFlag& flag : report_flags_) {
1206 if (flag.is_volatile)
1207 return false;
1208 }
1209 return true;
1210}
1211
sprang233bd872015-09-08 13:25:16 -07001212bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
1213 CriticalSectionScoped lock(critical_section_transport_.get());
1214 if (!cbTransport_)
1215 return false;
1216
1217 class Sender : public rtcp::RtcpPacket::PacketReadyCallback {
1218 public:
Peter Boströmac547a62015-09-17 23:03:57 +02001219 Sender(Transport* transport)
1220 : transport_(transport), send_failure_(false) {}
sprang233bd872015-09-08 13:25:16 -07001221
1222 void OnPacketReady(uint8_t* data, size_t length) override {
pbos2d566682015-09-28 09:59:31 -07001223 if (!transport_->SendRtcp(data, length))
sprang233bd872015-09-08 13:25:16 -07001224 send_failure_ = true;
1225 }
1226
1227 Transport* const transport_;
sprang233bd872015-09-08 13:25:16 -07001228 bool send_failure_;
Peter Boströmac547a62015-09-17 23:03:57 +02001229 } sender(cbTransport_);
sprang233bd872015-09-08 13:25:16 -07001230
1231 uint8_t buffer[IP_PACKET_SIZE];
1232 return packet.BuildExternalBuffer(buffer, IP_PACKET_SIZE, &sender) &&
1233 !sender.send_failure_;
1234}
1235
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001236} // namespace webrtc