blob: ea7931fadcd729c1ed149fe05a1f2f483443b00c [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(
135 int32_t id,
136 bool audio,
137 Clock* clock,
138 ReceiveStatistics* receive_statistics,
139 RtcpPacketTypeCounterObserver* packet_type_counter_observer)
Erik Språng242e22b2015-05-11 10:17:43 +0200140 : id_(id),
141 audio_(audio),
142 clock_(clock),
143 method_(kRtcpOff),
144 critical_section_transport_(
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000145 CriticalSectionWrapper::CreateCriticalSection()),
Erik Språng242e22b2015-05-11 10:17:43 +0200146 cbTransport_(nullptr),
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_));
178
179 builders_[kRtcpSr] = &RTCPSender::BuildSR;
180 builders_[kRtcpRr] = &RTCPSender::BuildRR;
Erik Språng0ea42d32015-06-25 14:46:16 +0200181 builders_[kRtcpSdes] = &RTCPSender::BuildSDES;
Erik Språng242e22b2015-05-11 10:17:43 +0200182 builders_[kRtcpPli] = &RTCPSender::BuildPLI;
183 builders_[kRtcpFir] = &RTCPSender::BuildFIR;
184 builders_[kRtcpSli] = &RTCPSender::BuildSLI;
185 builders_[kRtcpRpsi] = &RTCPSender::BuildRPSI;
186 builders_[kRtcpRemb] = &RTCPSender::BuildREMB;
187 builders_[kRtcpBye] = &RTCPSender::BuildBYE;
188 builders_[kRtcpApp] = &RTCPSender::BuildAPP;
189 builders_[kRtcpTmmbr] = &RTCPSender::BuildTMMBR;
190 builders_[kRtcpTmmbn] = &RTCPSender::BuildTMMBN;
191 builders_[kRtcpNack] = &RTCPSender::BuildNACK;
192 builders_[kRtcpXrVoipMetric] = &RTCPSender::BuildVoIPMetric;
193 builders_[kRtcpXrReceiverReferenceTime] =
194 &RTCPSender::BuildReceiverReferenceTime;
195 builders_[kRtcpXrDlrrReportBlock] = &RTCPSender::BuildDlrr;
niklase@google.com470e71d2011-07-07 08:21:25 +0000196}
197
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000198RTCPSender::~RTCPSender() {
niklase@google.com470e71d2011-07-07 08:21:25 +0000199}
200
Erik Språng61be2a42015-04-27 13:32:52 +0200201int32_t RTCPSender::RegisterSendTransport(Transport* outgoingTransport) {
Erik Språng242e22b2015-05-11 10:17:43 +0200202 CriticalSectionScoped lock(critical_section_transport_.get());
203 cbTransport_ = outgoingTransport;
Erik Språng61be2a42015-04-27 13:32:52 +0200204 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000205}
206
Erik Språng61be2a42015-04-27 13:32:52 +0200207RTCPMethod RTCPSender::Status() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200208 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
209 return method_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000210}
211
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000212void RTCPSender::SetRTCPStatus(RTCPMethod method) {
Erik Språng242e22b2015-05-11 10:17:43 +0200213 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
214 method_ = method;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000215
216 if (method == kRtcpOff)
217 return;
Erik Språng242e22b2015-05-11 10:17:43 +0200218 next_time_to_send_rtcp_ =
219 clock_->TimeInMilliseconds() +
220 (audio_ ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000221}
222
Erik Språng61be2a42015-04-27 13:32:52 +0200223bool RTCPSender::Sending() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200224 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
225 return sending_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000226}
227
Erik Språng61be2a42015-04-27 13:32:52 +0200228int32_t RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
229 bool sending) {
230 bool sendRTCPBye = false;
231 {
Erik Språng242e22b2015-05-11 10:17:43 +0200232 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000233
Erik Språng242e22b2015-05-11 10:17:43 +0200234 if (method_ != kRtcpOff) {
235 if (sending == false && sending_ == true) {
Erik Språng61be2a42015-04-27 13:32:52 +0200236 // Trigger RTCP bye
237 sendRTCPBye = true;
238 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000239 }
Erik Språng242e22b2015-05-11 10:17:43 +0200240 sending_ = sending;
Erik Språng61be2a42015-04-27 13:32:52 +0200241 }
242 if (sendRTCPBye)
243 return SendRTCP(feedback_state, kRtcpBye);
244 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000245}
246
Erik Språng61be2a42015-04-27 13:32:52 +0200247bool RTCPSender::REMB() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200248 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
249 return remb_enabled_;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000250}
251
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000252void RTCPSender::SetREMBStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200253 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
254 remb_enabled_ = enable;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000255}
256
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000257void RTCPSender::SetREMBData(uint32_t bitrate,
258 const std::vector<uint32_t>& ssrcs) {
Erik Språng242e22b2015-05-11 10:17:43 +0200259 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
260 remb_bitrate_ = bitrate;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000261 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000262
Erik Språng242e22b2015-05-11 10:17:43 +0200263 if (remb_enabled_)
264 SetFlag(kRtcpRemb, false);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000265 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
266 // throttled by the caller.
Erik Språng242e22b2015-05-11 10:17:43 +0200267 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000268}
269
Erik Språng61be2a42015-04-27 13:32:52 +0200270bool RTCPSender::TMMBR() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200271 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
272 return IsFlagPresent(RTCPPacketType::kRtcpTmmbr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000273}
274
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000275void RTCPSender::SetTMMBRStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200276 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
277 if (enable) {
278 SetFlag(RTCPPacketType::kRtcpTmmbr, false);
279 } else {
280 ConsumeFlag(RTCPPacketType::kRtcpTmmbr, true);
281 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000282}
283
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000284void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
Erik Språng242e22b2015-05-11 10:17:43 +0200285 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000286 start_timestamp_ = start_timestamp;
287}
288
289void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
290 int64_t capture_time_ms) {
Erik Språng242e22b2015-05-11 10:17:43 +0200291 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000292 last_rtp_timestamp_ = rtp_timestamp;
293 if (capture_time_ms < 0) {
294 // We don't currently get a capture time from VoiceEngine.
Erik Språng242e22b2015-05-11 10:17:43 +0200295 last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000296 } else {
297 last_frame_capture_time_ms_ = capture_time_ms;
298 }
299}
300
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000301void RTCPSender::SetSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200302 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000303
Erik Språng242e22b2015-05-11 10:17:43 +0200304 if (ssrc_ != 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200305 // not first SetSSRC, probably due to a collision
306 // schedule a new RTCP report
307 // make sure that we send a RTP packet
Erik Språng242e22b2015-05-11 10:17:43 +0200308 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
Erik Språng61be2a42015-04-27 13:32:52 +0200309 }
Erik Språng242e22b2015-05-11 10:17:43 +0200310 ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000311}
312
Erik Språng61be2a42015-04-27 13:32:52 +0200313void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200314 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
315 remote_ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000316}
317
Peter Boström9ba52f82015-06-01 14:12:28 +0200318int32_t RTCPSender::SetCNAME(const char* c_name) {
319 if (!c_name)
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000320 return -1;
321
henrikg91d6ede2015-09-17 00:24:34 -0700322 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
Erik Språng242e22b2015-05-11 10:17:43 +0200323 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200324 cname_ = c_name;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000325 return 0;
326}
327
Erik Språng0ea42d32015-06-25 14:46:16 +0200328int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC, const char* c_name) {
329 assert(c_name);
henrikg91d6ede2015-09-17 00:24:34 -0700330 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
Erik Språng242e22b2015-05-11 10:17:43 +0200331 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200332 if (csrc_cnames_.size() >= kRtpCsrcSize)
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000333 return -1;
Erik Språng0ea42d32015-06-25 14:46:16 +0200334
335 csrc_cnames_[SSRC] = c_name;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000336 return 0;
337}
338
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000339int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
Erik Språng242e22b2015-05-11 10:17:43 +0200340 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200341 auto it = csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000342
Erik Språng242e22b2015-05-11 10:17:43 +0200343 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000344 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200345
Erik Språng242e22b2015-05-11 10:17:43 +0200346 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000347 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000348}
349
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000350bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
niklase@google.com470e71d2011-07-07 08:21:25 +0000351/*
352 For audio we use a fix 5 sec interval
353
354 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000355 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
356 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000357
358
359From RFC 3550
360
361 MAX RTCP BW is 5% if the session BW
362 A send report is approximately 65 bytes inc CNAME
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000363 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000364
365 The RECOMMENDED value for the reduced minimum in seconds is 360
366 divided by the session bandwidth in kilobits/second. This minimum
367 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
368
369 If the participant has not yet sent an RTCP packet (the variable
370 initial is true), the constant Tmin is set to 2.5 seconds, else it
371 is set to 5 seconds.
372
373 The interval between RTCP packets is varied randomly over the
374 range [0.5,1.5] times the calculated interval to avoid unintended
375 synchronization of all participants
376
377 if we send
378 If the participant is a sender (we_sent true), the constant C is
379 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
380 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
381 number of senders.
382
383 if we receive only
384 If we_sent is not true, the constant C is set
385 to the average RTCP packet size divided by 75% of the RTCP
386 bandwidth. The constant n is set to the number of receivers
387 (members - senders). If the number of senders is greater than
388 25%, senders and receivers are treated together.
389
390 reconsideration NOT required for peer-to-peer
391 "timer reconsideration" is
392 employed. This algorithm implements a simple back-off mechanism
393 which causes users to hold back RTCP packet transmission if the
394 group sizes are increasing.
395
396 n = number of members
397 C = avg_size/(rtcpBW/4)
398
399 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
400
401 4. The calculated interval T is set to a number uniformly distributed
402 between 0.5 and 1.5 times the deterministic calculated interval.
403
404 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
405 for the fact that the timer reconsideration algorithm converges to
406 a value of the RTCP bandwidth below the intended average
407*/
408
Erik Språng242e22b2015-05-11 10:17:43 +0200409 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000410
Erik Språng242e22b2015-05-11 10:17:43 +0200411 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
xians@webrtc.org8738d272011-11-25 13:43:53 +0000412
Erik Språng242e22b2015-05-11 10:17:43 +0200413 if (method_ == kRtcpOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000414 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000415
Erik Språng242e22b2015-05-11 10:17:43 +0200416 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200417 // for video key-frames we want to send the RTCP before the large key-frame
418 // if we have a 100 ms margin
419 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
420 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000421
Erik Språng242e22b2015-05-11 10:17:43 +0200422 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200423 return true;
424 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200425 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200426 // wrap
427 return true;
428 }
429 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000430}
431
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000432int64_t RTCPSender::SendTimeOfSendReport(uint32_t sendReport) {
Erik Språng242e22b2015-05-11 10:17:43 +0200433 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000434
Erik Språng61be2a42015-04-27 13:32:52 +0200435 // This is only saved when we are the sender
Erik Språng242e22b2015-05-11 10:17:43 +0200436 if ((last_send_report_[0] == 0) || (sendReport == 0)) {
Erik Språng61be2a42015-04-27 13:32:52 +0200437 return 0; // will be ignored
438 } else {
439 for (int i = 0; i < RTCP_NUMBER_OF_SR; ++i) {
Erik Språng242e22b2015-05-11 10:17:43 +0200440 if (last_send_report_[i] == sendReport)
441 return last_rtcp_time_[i];
niklase@google.com470e71d2011-07-07 08:21:25 +0000442 }
Erik Språng61be2a42015-04-27 13:32:52 +0200443 }
444 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000445}
446
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000447bool RTCPSender::SendTimeOfXrRrReport(uint32_t mid_ntp,
448 int64_t* time_ms) const {
Erik Språng242e22b2015-05-11 10:17:43 +0200449 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000450
451 if (last_xr_rr_.empty()) {
452 return false;
453 }
454 std::map<uint32_t, int64_t>::const_iterator it = last_xr_rr_.find(mid_ntp);
455 if (it == last_xr_rr_.end()) {
456 return false;
457 }
458 *time_ms = it->second;
459 return true;
460}
461
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200462int32_t RTCPSender::AddReportBlock(const RTCPReportBlock& report_block) {
463 if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000464 LOG(LS_WARNING) << "Too many report blocks.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000465 return -1;
466 }
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200467 rtcp::ReportBlock* block = &report_blocks_[report_block.remoteSSRC];
468 block->To(report_block.remoteSSRC);
469 block->WithFractionLost(report_block.fractionLost);
470 block->WithCumulativeLost(report_block.cumulativeLost);
471 block->WithExtHighestSeqNum(report_block.extendedHighSeqNum);
472 block->WithJitter(report_block.jitter);
473 block->WithLastSr(report_block.lastSR);
474 block->WithDelayLastSr(report_block.delaySinceLastSR);
475
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000476 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000477}
478
Erik Språng242e22b2015-05-11 10:17:43 +0200479RTCPSender::BuildResult RTCPSender::BuildSR(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200480 for (int i = (RTCP_NUMBER_OF_SR - 2); i >= 0; i--) {
481 // shift old
Erik Språng242e22b2015-05-11 10:17:43 +0200482 last_send_report_[i + 1] = last_send_report_[i];
483 last_rtcp_time_[i + 1] = last_rtcp_time_[i];
Erik Språng61be2a42015-04-27 13:32:52 +0200484 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000485
Erik Språng242e22b2015-05-11 10:17:43 +0200486 last_rtcp_time_[0] = Clock::NtpToMs(ctx->ntp_sec, ctx->ntp_frac);
487 last_send_report_[0] = (ctx->ntp_sec << 16) + (ctx->ntp_frac >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000488
Erik Språng61be2a42015-04-27 13:32:52 +0200489 // The timestamp of this RTCP packet should be estimated as the timestamp of
490 // the frame being captured at this moment. We are calculating that
491 // timestamp as the last frame's timestamp + the time since the last frame
492 // was captured.
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200493 uint32_t rtp_timestamp =
494 start_timestamp_ + last_rtp_timestamp_ +
495 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) *
496 (ctx->feedback_state.frequency_hz / 1000);
niklase@google.com470e71d2011-07-07 08:21:25 +0000497
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200498 rtcp::SenderReport report;
499 report.From(ssrc_);
500 report.WithNtpSec(ctx->ntp_sec);
501 report.WithNtpFrac(ctx->ntp_frac);
502 report.WithRtpTimestamp(rtp_timestamp);
503 report.WithPacketCount(ctx->feedback_state.packets_sent);
504 report.WithOctetCount(ctx->feedback_state.media_bytes_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000505
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200506 for (auto it : report_blocks_)
507 report.WithReportBlock(it.second);
niklase@google.com470e71d2011-07-07 08:21:25 +0000508
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200509 PacketBuiltCallback callback(ctx);
Erik Språng72aa9a62015-07-31 16:16:02 +0200510 if (!callback.BuildPacket(report))
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200511 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000512
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200513 report_blocks_.clear();
Erik Språng242e22b2015-05-11 10:17:43 +0200514 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000515}
516
Erik Språng0ea42d32015-06-25 14:46:16 +0200517RTCPSender::BuildResult RTCPSender::BuildSDES(RtcpContext* ctx) {
518 size_t length_cname = cname_.length();
henrikg91d6ede2015-09-17 00:24:34 -0700519 RTC_CHECK_LT(length_cname, static_cast<size_t>(RTCP_CNAME_SIZE));
niklase@google.com470e71d2011-07-07 08:21:25 +0000520
Erik Språng0ea42d32015-06-25 14:46:16 +0200521 rtcp::Sdes sdes;
522 sdes.WithCName(ssrc_, cname_);
523
524 for (const auto it : csrc_cnames_)
525 sdes.WithCName(it.first, it.second);
526
527 PacketBuiltCallback callback(ctx);
Erik Språng72aa9a62015-07-31 16:16:02 +0200528 if (!callback.BuildPacket(sdes))
Erik Språng242e22b2015-05-11 10:17:43 +0200529 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000530
Erik Språng242e22b2015-05-11 10:17:43 +0200531 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000532}
533
Erik Språng242e22b2015-05-11 10:17:43 +0200534RTCPSender::BuildResult RTCPSender::BuildRR(RtcpContext* ctx) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200535 rtcp::ReceiverReport report;
536 report.From(ssrc_);
537 for (auto it : report_blocks_)
538 report.WithReportBlock(it.second);
539
540 PacketBuiltCallback callback(ctx);
Erik Språng72aa9a62015-07-31 16:16:02 +0200541 if (!callback.BuildPacket(report))
Erik Språng242e22b2015-05-11 10:17:43 +0200542 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200543
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200544 report_blocks_.clear();
Erik Språng242e22b2015-05-11 10:17:43 +0200545
546 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000547}
548
Erik Språng242e22b2015-05-11 10:17:43 +0200549RTCPSender::BuildResult RTCPSender::BuildPLI(RtcpContext* ctx) {
Erik Språng72aa9a62015-07-31 16:16:02 +0200550 rtcp::Pli pli;
551 pli.From(ssrc_);
552 pli.To(remote_ssrc_);
553
554 PacketBuiltCallback callback(ctx);
555 if (!callback.BuildPacket(pli))
Erik Språng242e22b2015-05-11 10:17:43 +0200556 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200557
Erik Språng242e22b2015-05-11 10:17:43 +0200558 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
559 "RTCPSender::PLI");
560 ++packet_type_counter_.pli_packets;
561 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
562 ssrc_, packet_type_counter_.pli_packets);
563
564 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +0200565}
566
Erik Språng242e22b2015-05-11 10:17:43 +0200567RTCPSender::BuildResult RTCPSender::BuildFIR(RtcpContext* ctx) {
Erik Språng242e22b2015-05-11 10:17:43 +0200568 if (!ctx->repeat)
sprang62dae192015-08-05 02:35:35 -0700569 ++sequence_number_fir_; // Do not increase if repetition.
niklase@google.com470e71d2011-07-07 08:21:25 +0000570
sprang62dae192015-08-05 02:35:35 -0700571 rtcp::Fir fir;
572 fir.From(ssrc_);
573 fir.To(remote_ssrc_);
574 fir.WithCommandSeqNum(sequence_number_fir_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000575
sprang62dae192015-08-05 02:35:35 -0700576 PacketBuiltCallback callback(ctx);
577 if (!callback.BuildPacket(fir))
578 return BuildResult::kTruncated;
Erik Språng242e22b2015-05-11 10:17:43 +0200579
580 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
581 "RTCPSender::FIR");
582 ++packet_type_counter_.fir_packets;
583 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
584 ssrc_, packet_type_counter_.fir_packets);
585
586 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000587}
588
589/*
590 0 1 2 3
591 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
592 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
593 | First | Number | PictureID |
594 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
595*/
Erik Språng242e22b2015-05-11 10:17:43 +0200596RTCPSender::BuildResult RTCPSender::BuildSLI(RtcpContext* ctx) {
sprang0365a272015-08-11 01:02:37 -0700597 rtcp::Sli sli;
598 sli.From(ssrc_);
599 sli.To(remote_ssrc_);
600 // Crop picture id to 6 least significant bits.
601 sli.WithPictureId(ctx->picture_id & 0x3F);
602 sli.WithFirstMb(0);
603 sli.WithNumberOfMb(0x1FFF); // 13 bits, only ones for now.
604
605 PacketBuiltCallback callback(ctx);
606 if (!callback.BuildPacket(sli))
Erik Språng242e22b2015-05-11 10:17:43 +0200607 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000608
Erik Språng242e22b2015-05-11 10:17:43 +0200609 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000610}
611
612/*
613 0 1 2 3
614 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
615 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
616 | PB |0| Payload Type| Native RPSI bit string |
617 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
618 | defined per codec ... | Padding (0) |
619 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
620*/
621/*
622* Note: not generic made for VP8
623*/
Erik Språng242e22b2015-05-11 10:17:43 +0200624RTCPSender::BuildResult RTCPSender::BuildRPSI(RtcpContext* ctx) {
625 if (ctx->feedback_state.send_payload_type == 0xFF)
626 return BuildResult::kError;
627
sprangcf7f54d2015-08-13 04:37:42 -0700628 rtcp::Rpsi rpsi;
629 rpsi.From(ssrc_);
630 rpsi.To(remote_ssrc_);
631 rpsi.WithPayloadType(ctx->feedback_state.send_payload_type);
632 rpsi.WithPictureId(ctx->picture_id);
633
634 PacketBuiltCallback callback(ctx);
635 if (!callback.BuildPacket(rpsi))
Erik Språng242e22b2015-05-11 10:17:43 +0200636 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000637
Erik Språng242e22b2015-05-11 10:17:43 +0200638 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000639}
640
Erik Språng242e22b2015-05-11 10:17:43 +0200641RTCPSender::BuildResult RTCPSender::BuildREMB(RtcpContext* ctx) {
sprangdd4edc52015-08-21 04:21:51 -0700642 rtcp::Remb remb;
643 remb.From(ssrc_);
644 for (uint32_t ssrc : remb_ssrcs_)
645 remb.AppliesTo(ssrc);
646 remb.WithBitrateBps(remb_bitrate_);
647
648 PacketBuiltCallback callback(ctx);
649 if (!callback.BuildPacket(remb))
Erik Språng242e22b2015-05-11 10:17:43 +0200650 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200651
Erik Språng242e22b2015-05-11 10:17:43 +0200652 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
653 "RTCPSender::REMB");
654
655 return BuildResult::kSuccess;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000656}
657
Erik Språng61be2a42015-04-27 13:32:52 +0200658void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
Erik Språng242e22b2015-05-11 10:17:43 +0200659 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
660 tmmbr_send_ = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000661}
662
Erik Språng242e22b2015-05-11 10:17:43 +0200663RTCPSender::BuildResult RTCPSender::BuildTMMBR(RtcpContext* ctx) {
664 if (ctx->feedback_state.module == NULL)
665 return BuildResult::kError;
Erik Språng61be2a42015-04-27 13:32:52 +0200666 // Before sending the TMMBR check the received TMMBN, only an owner is
667 // allowed to raise the bitrate:
668 // * If the sender is an owner of the TMMBN -> send TMMBR
669 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000670
Erik Språng61be2a42015-04-27 13:32:52 +0200671 // get current bounding set from RTCP receiver
672 bool tmmbrOwner = false;
673 // store in candidateSet, allocates one extra slot
Erik Språng242e22b2015-05-11 10:17:43 +0200674 TMMBRSet* candidateSet = tmmbr_help_.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000675
Erik Språng242e22b2015-05-11 10:17:43 +0200676 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
677 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
Erik Språng61be2a42015-04-27 13:32:52 +0200678 // since RTCPreceiver is not doing the reverse we should be fine
679 int32_t lengthOfBoundingSet =
Erik Språng242e22b2015-05-11 10:17:43 +0200680 ctx->feedback_state.module->BoundingSet(tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +0000681
Erik Språng61be2a42015-04-27 13:32:52 +0200682 if (lengthOfBoundingSet > 0) {
683 for (int32_t i = 0; i < lengthOfBoundingSet; i++) {
Erik Språng242e22b2015-05-11 10:17:43 +0200684 if (candidateSet->Tmmbr(i) == tmmbr_send_ &&
685 candidateSet->PacketOH(i) == packet_oh_send_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200686 // do not send the same tuple
Erik Språng242e22b2015-05-11 10:17:43 +0200687 return BuildResult::kAborted;
Erik Språng61be2a42015-04-27 13:32:52 +0200688 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000689 }
Erik Språng61be2a42015-04-27 13:32:52 +0200690 if (!tmmbrOwner) {
691 // use received bounding set as candidate set
692 // add current tuple
Erik Språng242e22b2015-05-11 10:17:43 +0200693 candidateSet->SetEntry(lengthOfBoundingSet, tmmbr_send_, packet_oh_send_,
694 ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200695 int numCandidates = lengthOfBoundingSet + 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000696
Erik Språng61be2a42015-04-27 13:32:52 +0200697 // find bounding set
698 TMMBRSet* boundingSet = NULL;
Erik Språng242e22b2015-05-11 10:17:43 +0200699 int numBoundingSet = tmmbr_help_.FindTMMBRBoundingSet(boundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200700 if (numBoundingSet > 0 || numBoundingSet <= numCandidates)
Erik Språng242e22b2015-05-11 10:17:43 +0200701 tmmbrOwner = tmmbr_help_.IsOwner(ssrc_, numBoundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200702 if (!tmmbrOwner) {
703 // did not enter bounding set, no meaning to send this request
Erik Språng242e22b2015-05-11 10:17:43 +0200704 return BuildResult::kAborted;
Erik Språng61be2a42015-04-27 13:32:52 +0200705 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000706 }
Erik Språng61be2a42015-04-27 13:32:52 +0200707 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000708
Erik Språng242e22b2015-05-11 10:17:43 +0200709 if (tmmbr_send_) {
sprang81a3e602015-08-21 05:30:11 -0700710 rtcp::Tmmbr tmmbr;
711 tmmbr.From(ssrc_);
712 tmmbr.To(remote_ssrc_);
713 tmmbr.WithBitrateKbps(tmmbr_send_);
714 tmmbr.WithOverhead(packet_oh_send_);
715
716 PacketBuiltCallback callback(ctx);
717 if (!callback.BuildPacket(tmmbr))
Erik Språng242e22b2015-05-11 10:17:43 +0200718 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200719 }
Erik Språng242e22b2015-05-11 10:17:43 +0200720 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +0200721}
722
Erik Språng242e22b2015-05-11 10:17:43 +0200723RTCPSender::BuildResult RTCPSender::BuildTMMBN(RtcpContext* ctx) {
724 TMMBRSet* boundingSet = tmmbr_help_.BoundingSetToSend();
Erik Språng61be2a42015-04-27 13:32:52 +0200725 if (boundingSet == NULL)
Erik Språng242e22b2015-05-11 10:17:43 +0200726 return BuildResult::kError;
Erik Språng61be2a42015-04-27 13:32:52 +0200727
sprangd83df502015-08-27 01:05:08 -0700728 rtcp::Tmmbn tmmbn;
729 tmmbn.From(ssrc_);
730 for (uint32_t i = 0; i < boundingSet->lengthOfSet(); i++) {
731 if (boundingSet->Tmmbr(i) > 0) {
732 tmmbn.WithTmmbr(boundingSet->Ssrc(i), boundingSet->Tmmbr(i),
733 boundingSet->PacketOH(i));
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000734 }
Erik Språng61be2a42015-04-27 13:32:52 +0200735 }
sprangd83df502015-08-27 01:05:08 -0700736
737 PacketBuiltCallback callback(ctx);
738 if (!callback.BuildPacket(tmmbn))
739 return BuildResult::kTruncated;
Erik Språng242e22b2015-05-11 10:17:43 +0200740
741 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000742}
743
Erik Språng242e22b2015-05-11 10:17:43 +0200744RTCPSender::BuildResult RTCPSender::BuildAPP(RtcpContext* ctx) {
Erik Språng521875a2015-09-01 10:11:16 +0200745 rtcp::App app;
746 app.From(ssrc_);
747 app.WithSubType(app_sub_type_);
748 app.WithName(app_name_);
749 app.WithData(app_data_.get(), app_length_);
750
751 PacketBuiltCallback callback(ctx);
752 if (!callback.BuildPacket(app))
Erik Språng242e22b2015-05-11 10:17:43 +0200753 return BuildResult::kTruncated;
Erik Språng242e22b2015-05-11 10:17:43 +0200754
755 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +0200756}
757
Erik Språng242e22b2015-05-11 10:17:43 +0200758RTCPSender::BuildResult RTCPSender::BuildNACK(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200759 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200760 if (ctx->position + 16 >= IP_PACKET_SIZE) {
Erik Språng61be2a42015-04-27 13:32:52 +0200761 LOG(LS_WARNING) << "Failed to build NACK.";
Erik Språng242e22b2015-05-11 10:17:43 +0200762 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200763 }
764
Erik Språng242e22b2015-05-11 10:17:43 +0200765 // int size, uint16_t* nack_list
Erik Språng61be2a42015-04-27 13:32:52 +0200766 // add nack list
767 uint8_t FMT = 1;
Erik Språng242e22b2015-05-11 10:17:43 +0200768 *ctx->AllocateData(1) = 0x80 + FMT;
769 *ctx->AllocateData(1) = 205;
Erik Språng61be2a42015-04-27 13:32:52 +0200770
Erik Språng242e22b2015-05-11 10:17:43 +0200771 *ctx->AllocateData(1) = 0;
772 int nack_size_pos_ = ctx->position;
773 *ctx->AllocateData(1) = 3; // setting it to one kNACK signal as default
Erik Språng61be2a42015-04-27 13:32:52 +0200774
775 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200776 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200777
778 // Add the remote SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200779 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200780
781 // Build NACK bitmasks and write them to the RTCP message.
782 // The nack list should be sorted and not contain duplicates if one
783 // wants to build the smallest rtcp nack packet.
784 int numOfNackFields = 0;
785 int maxNackFields =
Erik Språng242e22b2015-05-11 10:17:43 +0200786 std::min<int>(kRtcpMaxNackFields, (IP_PACKET_SIZE - ctx->position) / 4);
Erik Språng61be2a42015-04-27 13:32:52 +0200787 int i = 0;
Erik Språng242e22b2015-05-11 10:17:43 +0200788 while (i < ctx->nack_size && numOfNackFields < maxNackFields) {
789 uint16_t nack = ctx->nack_list[i++];
Erik Språng61be2a42015-04-27 13:32:52 +0200790 uint16_t bitmask = 0;
Erik Språng242e22b2015-05-11 10:17:43 +0200791 while (i < ctx->nack_size) {
792 int shift = static_cast<uint16_t>(ctx->nack_list[i] - nack) - 1;
Erik Språng61be2a42015-04-27 13:32:52 +0200793 if (shift >= 0 && shift <= 15) {
794 bitmask |= (1 << shift);
795 ++i;
796 } else {
797 break;
798 }
799 }
800 // Write the sequence number and the bitmask to the packet.
Erik Språng242e22b2015-05-11 10:17:43 +0200801 assert(ctx->position + 4 < IP_PACKET_SIZE);
802 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2), nack);
803 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2), bitmask);
Erik Språng61be2a42015-04-27 13:32:52 +0200804 numOfNackFields++;
805 }
Erik Språng242e22b2015-05-11 10:17:43 +0200806 ctx->buffer[nack_size_pos_] = static_cast<uint8_t>(2 + numOfNackFields);
Erik Språng61be2a42015-04-27 13:32:52 +0200807
Erik Språng242e22b2015-05-11 10:17:43 +0200808 if (i != ctx->nack_size)
Erik Språng61be2a42015-04-27 13:32:52 +0200809 LOG(LS_WARNING) << "Nack list too large for one packet.";
810
811 // Report stats.
812 NACKStringBuilder stringBuilder;
813 for (int idx = 0; idx < i; ++idx) {
Erik Språng242e22b2015-05-11 10:17:43 +0200814 stringBuilder.PushNACK(ctx->nack_list[idx]);
815 nack_stats_.ReportRequest(ctx->nack_list[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +0200816 }
Erik Språng61be2a42015-04-27 13:32:52 +0200817 packet_type_counter_.nack_requests = nack_stats_.requests();
818 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +0200819
820 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
821 "RTCPSender::NACK", "nacks",
822 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
823 ++packet_type_counter_.nack_packets;
824 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
825 ssrc_, packet_type_counter_.nack_packets);
826
827 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +0200828}
829
Erik Språng242e22b2015-05-11 10:17:43 +0200830RTCPSender::BuildResult RTCPSender::BuildBYE(RtcpContext* ctx) {
sprangd8ee4f92015-08-24 03:25:19 -0700831 rtcp::Bye bye;
832 bye.From(ssrc_);
833 for (uint32_t csrc : csrcs_)
834 bye.WithCsrc(csrc);
835
836 PacketBuiltCallback callback(ctx);
837 if (!callback.BuildPacket(bye))
Erik Språng242e22b2015-05-11 10:17:43 +0200838 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000839
Erik Språng242e22b2015-05-11 10:17:43 +0200840 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000841}
842
Erik Språng242e22b2015-05-11 10:17:43 +0200843RTCPSender::BuildResult RTCPSender::BuildReceiverReferenceTime(
844 RtcpContext* ctx) {
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000845
Erik Språng61be2a42015-04-27 13:32:52 +0200846 if (last_xr_rr_.size() >= RTCP_NUMBER_OF_SR)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000847 last_xr_rr_.erase(last_xr_rr_.begin());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000848 last_xr_rr_.insert(std::pair<uint32_t, int64_t>(
Erik Språng242e22b2015-05-11 10:17:43 +0200849 RTCPUtility::MidNtp(ctx->ntp_sec, ctx->ntp_frac),
850 Clock::NtpToMs(ctx->ntp_sec, ctx->ntp_frac)));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000851
Erik Språngca28fdc2015-08-31 14:00:50 +0200852 rtcp::Xr xr;
853 xr.From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000854
Erik Språngca28fdc2015-08-31 14:00:50 +0200855 rtcp::Rrtr rrtr;
856 rrtr.WithNtpSec(ctx->ntp_sec);
857 rrtr.WithNtpFrac(ctx->ntp_frac);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000858
Erik Språngca28fdc2015-08-31 14:00:50 +0200859 xr.WithRrtr(&rrtr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000860
Erik Språngca28fdc2015-08-31 14:00:50 +0200861 // TODO(sprang): Merge XR report sending to contain all of RRTR, DLRR, VOIP?
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000862
Erik Språngca28fdc2015-08-31 14:00:50 +0200863 PacketBuiltCallback callback(ctx);
864 if (!callback.BuildPacket(xr))
865 return BuildResult::kTruncated;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000866
Erik Språng242e22b2015-05-11 10:17:43 +0200867 return BuildResult::kSuccess;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000868}
869
Erik Språng242e22b2015-05-11 10:17:43 +0200870RTCPSender::BuildResult RTCPSender::BuildDlrr(RtcpContext* ctx) {
Erik Språngca28fdc2015-08-31 14:00:50 +0200871 rtcp::Xr xr;
872 xr.From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000873
Erik Språngca28fdc2015-08-31 14:00:50 +0200874 rtcp::Dlrr dlrr;
Erik Språng242e22b2015-05-11 10:17:43 +0200875 const RtcpReceiveTimeInfo& info = ctx->feedback_state.last_xr_rr;
Erik Språngca28fdc2015-08-31 14:00:50 +0200876 dlrr.WithDlrrItem(info.sourceSSRC, info.lastRR, info.delaySinceLastRR);
877
878 xr.WithDlrr(&dlrr);
879
880 PacketBuiltCallback callback(ctx);
881 if (!callback.BuildPacket(xr))
882 return BuildResult::kTruncated;
Erik Språng242e22b2015-05-11 10:17:43 +0200883
884 return BuildResult::kSuccess;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000885}
886
Erik Språng242e22b2015-05-11 10:17:43 +0200887// TODO(sprang): Add a unit test for this, or remove if the code isn't used.
888RTCPSender::BuildResult RTCPSender::BuildVoIPMetric(RtcpContext* ctx) {
Erik Språngca28fdc2015-08-31 14:00:50 +0200889 rtcp::Xr xr;
890 xr.From(ssrc_);
891
892 rtcp::VoipMetric voip;
893 voip.To(remote_ssrc_);
894 voip.LossRate(xr_voip_metric_.lossRate);
895 voip.DiscardRate(xr_voip_metric_.discardRate);
896 voip.BurstDensity(xr_voip_metric_.burstDensity);
897 voip.GapDensity(xr_voip_metric_.gapDensity);
898 voip.BurstDuration(xr_voip_metric_.burstDuration);
899 voip.GapDuration(xr_voip_metric_.gapDuration);
900 voip.RoundTripDelay(xr_voip_metric_.roundTripDelay);
901 voip.EndSystemDelay(xr_voip_metric_.endSystemDelay);
902 voip.SignalLevel(xr_voip_metric_.signalLevel);
903 voip.NoiseLevel(xr_voip_metric_.noiseLevel);
904 voip.Rerl(xr_voip_metric_.RERL);
905 voip.Gmin(xr_voip_metric_.Gmin);
906 voip.Rfactor(xr_voip_metric_.Rfactor);
907 voip.ExtRfactor(xr_voip_metric_.extRfactor);
908 voip.MosLq(xr_voip_metric_.MOSLQ);
909 voip.MosCq(xr_voip_metric_.MOSCQ);
910 voip.RxConfig(xr_voip_metric_.RXconfig);
911 voip.JbNominal(xr_voip_metric_.JBnominal);
912 voip.JbMax(xr_voip_metric_.JBmax);
913 voip.JbAbsMax(xr_voip_metric_.JBabsMax);
914
915 xr.WithVoipMetric(&voip);
916
917 PacketBuiltCallback callback(ctx);
918 if (!callback.BuildPacket(xr))
Erik Språng242e22b2015-05-11 10:17:43 +0200919 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000920
Erik Språng242e22b2015-05-11 10:17:43 +0200921 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000922}
923
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000924int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200925 RTCPPacketType packetType,
926 int32_t nack_size,
927 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000928 bool repeat,
929 uint64_t pictureID) {
Erik Språng242e22b2015-05-11 10:17:43 +0200930 return SendCompoundRTCP(
931 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
932 nack_size, nack_list, repeat, pictureID);
933}
934
935int32_t RTCPSender::SendCompoundRTCP(
936 const FeedbackState& feedback_state,
937 const std::set<RTCPPacketType>& packetTypes,
938 int32_t nack_size,
939 const uint16_t* nack_list,
940 bool repeat,
941 uint64_t pictureID) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000942 {
Erik Språng242e22b2015-05-11 10:17:43 +0200943 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
944 if (method_ == kRtcpOff) {
Erik Språng61be2a42015-04-27 13:32:52 +0200945 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
946 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +0000947 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000948 }
949 uint8_t rtcp_buffer[IP_PACKET_SIZE];
Erik Språng242e22b2015-05-11 10:17:43 +0200950 int rtcp_length =
951 PrepareRTCP(feedback_state, packetTypes, nack_size, nack_list, repeat,
952 pictureID, rtcp_buffer, IP_PACKET_SIZE);
Erik Språng61be2a42015-04-27 13:32:52 +0200953
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000954 // Sanity don't send empty packets.
Erik Språng242e22b2015-05-11 10:17:43 +0200955 if (rtcp_length <= 0)
956 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200957
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000958 return SendToNetwork(rtcp_buffer, static_cast<size_t>(rtcp_length));
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000959}
960
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000961int RTCPSender::PrepareRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200962 const std::set<RTCPPacketType>& packetTypes,
963 int32_t nack_size,
964 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000965 bool repeat,
966 uint64_t pictureID,
967 uint8_t* rtcp_buffer,
968 int buffer_size) {
Erik Språng242e22b2015-05-11 10:17:43 +0200969 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000970
Erik Språng242e22b2015-05-11 10:17:43 +0200971 RtcpContext context(feedback_state, nack_size, nack_list, repeat, pictureID,
972 rtcp_buffer, buffer_size);
973
974 // Add all flags as volatile. Non volatile entries will not be overwritten
975 // and all new volatile flags added will be consumed by the end of this call.
976 SetFlags(packetTypes, true);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000977
Erik Språng61be2a42015-04-27 13:32:52 +0200978 if (packet_type_counter_.first_packet_time_ms == -1)
Erik Språng242e22b2015-05-11 10:17:43 +0200979 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språng61be2a42015-04-27 13:32:52 +0200980
Erik Språng242e22b2015-05-11 10:17:43 +0200981 bool generate_report;
982 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
983 // Report type already explicitly set, don't automatically populate.
984 generate_report = true;
henrikg91d6ede2015-09-17 00:24:34 -0700985 RTC_DCHECK(ConsumeFlag(kRtcpReport) == false);
Erik Språng242e22b2015-05-11 10:17:43 +0200986 } else {
987 generate_report =
988 (ConsumeFlag(kRtcpReport) && method_ == kRtcpNonCompound) ||
989 method_ == kRtcpCompound;
990 if (generate_report)
991 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000992 }
993
Erik Språng0ea42d32015-06-25 14:46:16 +0200994 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
Erik Språng242e22b2015-05-11 10:17:43 +0200995 SetFlag(kRtcpSdes, true);
996
997 // We need to send our NTP even if we haven't received any reports.
998 clock_->CurrentNtp(context.ntp_sec, context.ntp_frac);
999
1000 if (generate_report) {
1001 if (!sending_ && xr_send_receiver_reference_time_enabled_)
1002 SetFlag(kRtcpXrReceiverReferenceTime, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001003 if (feedback_state.has_last_xr_rr)
Erik Språng242e22b2015-05-11 10:17:43 +02001004 SetFlag(kRtcpXrDlrrReportBlock, true);
1005
1006 // generate next time to send an RTCP report
Erik Språng61be2a42015-04-27 13:32:52 +02001007 // seeded from RTP constructor
1008 int32_t random = rand() % 1000;
1009 int32_t timeToNext = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001010
Erik Språng242e22b2015-05-11 10:17:43 +02001011 if (audio_) {
Erik Språng61be2a42015-04-27 13:32:52 +02001012 timeToNext = (RTCP_INTERVAL_AUDIO_MS / 2) +
1013 (RTCP_INTERVAL_AUDIO_MS * random / 1000);
1014 } else {
1015 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
Erik Språng242e22b2015-05-11 10:17:43 +02001016 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +02001017 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
1018 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
1019 if (send_bitrate_kbit != 0)
1020 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001021 }
Erik Språng61be2a42015-04-27 13:32:52 +02001022 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
1023 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
1024 timeToNext = (minIntervalMs / 2) + (minIntervalMs * random / 1000);
1025 }
Erik Språng242e22b2015-05-11 10:17:43 +02001026 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001027
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001028 StatisticianMap statisticians =
1029 receive_statistics_->GetActiveStatisticians();
1030 if (!statisticians.empty()) {
Erik Språng61be2a42015-04-27 13:32:52 +02001031 for (auto it = statisticians.begin(); it != statisticians.end(); ++it) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001032 RTCPReportBlock report_block;
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001033 if (PrepareReport(feedback_state, it->first, it->second,
1034 &report_block)) {
1035 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) {
Erik Språng242e22b2015-05-11 10:17:43 +02001120 CriticalSectionScoped lock(critical_section_transport_.get());
1121 if (cbTransport_) {
1122 if (cbTransport_->SendRTCPPacket(id_, dataBuffer, length) > 0)
Erik Språng61be2a42015-04-27 13:32:52 +02001123 return 0;
1124 }
1125 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001126}
1127
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001128void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
1129 assert(csrcs.size() <= kRtpCsrcSize);
Erik Språng242e22b2015-05-11 10:17:43 +02001130 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001131 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +00001132}
1133
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001134int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
1135 uint32_t name,
1136 const uint8_t* data,
1137 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +02001138 if (length % 4 != 0) {
1139 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
1140 return -1;
1141 }
Erik Språng242e22b2015-05-11 10:17:43 +02001142 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +00001143
Erik Språng242e22b2015-05-11 10:17:43 +02001144 SetFlag(kRtcpApp, true);
1145 app_sub_type_ = subType;
1146 app_name_ = name;
1147 app_data_.reset(new uint8_t[length]);
1148 app_length_ = length;
1149 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +02001150 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001151}
1152
Erik Språng61be2a42015-04-27 13:32:52 +02001153int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
Erik Språng242e22b2015-05-11 10:17:43 +02001154 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1155 memcpy(&xr_voip_metric_, VoIPMetric, sizeof(RTCPVoIPMetric));
niklase@google.com470e71d2011-07-07 08:21:25 +00001156
Erik Språng242e22b2015-05-11 10:17:43 +02001157 SetFlag(kRtcpXrVoipMetric, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001158 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001159}
1160
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001161void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +02001162 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1163 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001164}
1165
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00001166bool RTCPSender::RtcpXrReceiverReferenceTime() const {
Erik Språng242e22b2015-05-11 10:17:43 +02001167 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1168 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00001169}
1170
niklase@google.com470e71d2011-07-07 08:21:25 +00001171// no callbacks allowed inside this function
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001172int32_t RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
1173 uint32_t maxBitrateKbit) {
Erik Språng242e22b2015-05-11 10:17:43 +02001174 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +00001175
Erik Språng242e22b2015-05-11 10:17:43 +02001176 if (0 == tmmbr_help_.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit)) {
1177 SetFlag(kRtcpTmmbn, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001178 return 0;
1179 }
1180 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001181}
Erik Språng61be2a42015-04-27 13:32:52 +02001182
Erik Språng242e22b2015-05-11 10:17:43 +02001183void RTCPSender::SetFlag(RTCPPacketType type, bool is_volatile) {
1184 report_flags_.insert(ReportFlag(type, is_volatile));
1185}
1186
1187void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
1188 bool is_volatile) {
1189 for (RTCPPacketType type : types)
1190 SetFlag(type, is_volatile);
1191}
1192
1193bool RTCPSender::IsFlagPresent(RTCPPacketType type) const {
1194 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
1195}
1196
1197bool RTCPSender::ConsumeFlag(RTCPPacketType type, bool forced) {
1198 auto it = report_flags_.find(ReportFlag(type, false));
1199 if (it == report_flags_.end())
1200 return false;
1201 if (it->is_volatile || forced)
1202 report_flags_.erase((it));
1203 return true;
1204}
1205
1206bool RTCPSender::AllVolatileFlagsConsumed() const {
1207 for (const ReportFlag& flag : report_flags_) {
1208 if (flag.is_volatile)
1209 return false;
1210 }
1211 return true;
1212}
1213
sprang233bd872015-09-08 13:25:16 -07001214bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
1215 CriticalSectionScoped lock(critical_section_transport_.get());
1216 if (!cbTransport_)
1217 return false;
1218
1219 class Sender : public rtcp::RtcpPacket::PacketReadyCallback {
1220 public:
1221 Sender(Transport* transport, int32_t id)
1222 : transport_(transport), id_(id), send_failure_(false) {}
1223
1224 void OnPacketReady(uint8_t* data, size_t length) override {
1225 if (transport_->SendRTCPPacket(id_, data, length) <= 0)
1226 send_failure_ = true;
1227 }
1228
1229 Transport* const transport_;
1230 int32_t id_;
1231 bool send_failure_;
1232 } sender(cbTransport_, id_);
1233
1234 uint8_t buffer[IP_PACKET_SIZE];
1235 return packet.BuildExternalBuffer(buffer, IP_PACKET_SIZE, &sender) &&
1236 !sender.send_failure_;
1237}
1238
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001239} // namespace webrtc