blob: e3e9e3fef7e1e8b262cd6024de6cc4981479669b [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"
24#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +000025#include "webrtc/system_wrappers/interface/logging.h"
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000026#include "webrtc/system_wrappers/interface/trace_event.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000027
niklase@google.com470e71d2011-07-07 08:21:25 +000028namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000029
30using RTCPUtility::RTCPCnameInformation;
31
Erik Språng61be2a42015-04-27 13:32:52 +020032NACKStringBuilder::NACKStringBuilder()
Erik Språng242e22b2015-05-11 10:17:43 +020033 : stream_(""), count_(0), prevNack_(0), consecutive_(false) {
edjee@google.com79b02892013-04-04 19:43:34 +000034}
35
pbos@webrtc.orgf3e4cee2013-07-31 15:17:19 +000036NACKStringBuilder::~NACKStringBuilder() {}
37
pbos@webrtc.org2f446732013-04-08 11:08:41 +000038void NACKStringBuilder::PushNACK(uint16_t nack)
edjee@google.com79b02892013-04-04 19:43:34 +000039{
Erik Språng242e22b2015-05-11 10:17:43 +020040 if (count_ == 0) {
41 stream_ << nack;
42 } else if (nack == prevNack_ + 1) {
43 consecutive_ = true;
Erik Språng61be2a42015-04-27 13:32:52 +020044 } else {
Erik Språng242e22b2015-05-11 10:17:43 +020045 if (consecutive_) {
46 stream_ << "-" << prevNack_;
47 consecutive_ = false;
edjee@google.com79b02892013-04-04 19:43:34 +000048 }
Erik Språng242e22b2015-05-11 10:17:43 +020049 stream_ << "," << nack;
Erik Språng61be2a42015-04-27 13:32:52 +020050 }
Erik Språng242e22b2015-05-11 10:17:43 +020051 count_++;
52 prevNack_ = nack;
edjee@google.com79b02892013-04-04 19:43:34 +000053}
54
Erik Språng61be2a42015-04-27 13:32:52 +020055std::string NACKStringBuilder::GetResult() {
Erik Språng242e22b2015-05-11 10:17:43 +020056 if (consecutive_) {
57 stream_ << "-" << prevNack_;
58 consecutive_ = false;
Erik Språng61be2a42015-04-27 13:32:52 +020059 }
Erik Språng242e22b2015-05-11 10:17:43 +020060 return stream_.str();
edjee@google.com79b02892013-04-04 19:43:34 +000061}
62
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000063RTCPSender::FeedbackState::FeedbackState()
64 : send_payload_type(0),
65 frequency_hz(0),
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +000066 packets_sent(0),
67 media_bytes_sent(0),
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000068 send_bitrate(0),
69 last_rr_ntp_secs(0),
70 last_rr_ntp_frac(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000071 remote_sr(0),
Erik Språng61be2a42015-04-27 13:32:52 +020072 has_last_xr_rr(false),
73 module(nullptr) {
74}
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000075
Erik Språng242e22b2015-05-11 10:17:43 +020076struct RTCPSender::RtcpContext {
77 RtcpContext(const FeedbackState& feedback_state,
78 int32_t nack_size,
79 const uint16_t* nack_list,
80 bool repeat,
81 uint64_t picture_id,
82 uint8_t* buffer,
83 uint32_t buffer_size)
84 : feedback_state(feedback_state),
85 nack_size(nack_size),
86 nack_list(nack_list),
87 repeat(repeat),
88 picture_id(picture_id),
89 buffer(buffer),
90 buffer_size(buffer_size),
91 ntp_sec(0),
92 ntp_frac(0),
Erik Språng242e22b2015-05-11 10:17:43 +020093 position(0) {}
94
95 uint8_t* AllocateData(uint32_t bytes) {
96 DCHECK_LE(position + bytes, buffer_size);
97 uint8_t* ptr = &buffer[position];
98 position += bytes;
99 return ptr;
100 }
101
102 const FeedbackState& feedback_state;
103 int32_t nack_size;
104 const uint16_t* nack_list;
105 bool repeat;
106 uint64_t picture_id;
107 uint8_t* buffer;
108 uint32_t buffer_size;
109 uint32_t ntp_sec;
110 uint32_t ntp_frac;
Erik Språng242e22b2015-05-11 10:17:43 +0200111 uint32_t position;
112};
113
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200114// TODO(sprang): Once all builders use RtcpPacket, call SendToNetwork() here.
115class RTCPSender::PacketBuiltCallback
116 : public rtcp::RtcpPacket::PacketReadyCallback {
117 public:
118 PacketBuiltCallback(RtcpContext* context) : context_(context) {}
119 virtual ~PacketBuiltCallback() {}
120 void OnPacketReady(uint8_t* data, size_t length) override {
121 context_->position += length;
122 }
Erik Språng72aa9a62015-07-31 16:16:02 +0200123 bool BuildPacket(const rtcp::RtcpPacket& packet) {
124 return packet.BuildExternalBuffer(
125 &context_->buffer[context_->position],
126 context_->buffer_size - context_->position, this);
127 }
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200128
129 private:
130 RtcpContext* const context_;
131};
132
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000133RTCPSender::RTCPSender(
134 int32_t id,
135 bool audio,
136 Clock* clock,
137 ReceiveStatistics* receive_statistics,
138 RtcpPacketTypeCounterObserver* packet_type_counter_observer)
Erik Språng242e22b2015-05-11 10:17:43 +0200139 : id_(id),
140 audio_(audio),
141 clock_(clock),
142 method_(kRtcpOff),
143 critical_section_transport_(
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000144 CriticalSectionWrapper::CreateCriticalSection()),
Erik Språng242e22b2015-05-11 10:17:43 +0200145 cbTransport_(nullptr),
niklase@google.com470e71d2011-07-07 08:21:25 +0000146
Erik Språng242e22b2015-05-11 10:17:43 +0200147 critical_section_rtcp_sender_(
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000148 CriticalSectionWrapper::CreateCriticalSection()),
Erik Språng242e22b2015-05-11 10:17:43 +0200149 using_nack_(false),
150 sending_(false),
151 remb_enabled_(false),
Erik Språng242e22b2015-05-11 10:17:43 +0200152 next_time_to_send_rtcp_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000153 start_timestamp_(0),
154 last_rtp_timestamp_(0),
155 last_frame_capture_time_ms_(-1),
Erik Språng242e22b2015-05-11 10:17:43 +0200156 ssrc_(0),
157 remote_ssrc_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000158 receive_statistics_(receive_statistics),
niklase@google.com470e71d2011-07-07 08:21:25 +0000159
Erik Språng242e22b2015-05-11 10:17:43 +0200160 sequence_number_fir_(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000161
Erik Språng242e22b2015-05-11 10:17:43 +0200162 remb_bitrate_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000163
Erik Språng242e22b2015-05-11 10:17:43 +0200164 tmmbr_help_(),
165 tmmbr_send_(0),
166 packet_oh_send_(0),
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000167
Erik Språng242e22b2015-05-11 10:17:43 +0200168 app_sub_type_(0),
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200169 app_name_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200170 app_data_(nullptr),
171 app_length_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000172
Erik Språng242e22b2015-05-11 10:17:43 +0200173 xr_send_receiver_reference_time_enabled_(false),
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000174 packet_type_counter_observer_(packet_type_counter_observer) {
Erik Språng242e22b2015-05-11 10:17:43 +0200175 memset(last_send_report_, 0, sizeof(last_send_report_));
176 memset(last_rtcp_time_, 0, sizeof(last_rtcp_time_));
177
178 builders_[kRtcpSr] = &RTCPSender::BuildSR;
179 builders_[kRtcpRr] = &RTCPSender::BuildRR;
Erik Språng0ea42d32015-06-25 14:46:16 +0200180 builders_[kRtcpSdes] = &RTCPSender::BuildSDES;
Erik Språng242e22b2015-05-11 10:17:43 +0200181 builders_[kRtcpPli] = &RTCPSender::BuildPLI;
182 builders_[kRtcpFir] = &RTCPSender::BuildFIR;
183 builders_[kRtcpSli] = &RTCPSender::BuildSLI;
184 builders_[kRtcpRpsi] = &RTCPSender::BuildRPSI;
185 builders_[kRtcpRemb] = &RTCPSender::BuildREMB;
186 builders_[kRtcpBye] = &RTCPSender::BuildBYE;
187 builders_[kRtcpApp] = &RTCPSender::BuildAPP;
188 builders_[kRtcpTmmbr] = &RTCPSender::BuildTMMBR;
189 builders_[kRtcpTmmbn] = &RTCPSender::BuildTMMBN;
190 builders_[kRtcpNack] = &RTCPSender::BuildNACK;
191 builders_[kRtcpXrVoipMetric] = &RTCPSender::BuildVoIPMetric;
192 builders_[kRtcpXrReceiverReferenceTime] =
193 &RTCPSender::BuildReceiverReferenceTime;
194 builders_[kRtcpXrDlrrReportBlock] = &RTCPSender::BuildDlrr;
niklase@google.com470e71d2011-07-07 08:21:25 +0000195}
196
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000197RTCPSender::~RTCPSender() {
niklase@google.com470e71d2011-07-07 08:21:25 +0000198}
199
Erik Språng61be2a42015-04-27 13:32:52 +0200200int32_t RTCPSender::RegisterSendTransport(Transport* outgoingTransport) {
Erik Språng242e22b2015-05-11 10:17:43 +0200201 CriticalSectionScoped lock(critical_section_transport_.get());
202 cbTransport_ = outgoingTransport;
Erik Språng61be2a42015-04-27 13:32:52 +0200203 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000204}
205
Erik Språng61be2a42015-04-27 13:32:52 +0200206RTCPMethod RTCPSender::Status() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200207 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
208 return method_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000209}
210
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000211void RTCPSender::SetRTCPStatus(RTCPMethod method) {
Erik Språng242e22b2015-05-11 10:17:43 +0200212 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
213 method_ = method;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000214
215 if (method == kRtcpOff)
216 return;
Erik Språng242e22b2015-05-11 10:17:43 +0200217 next_time_to_send_rtcp_ =
218 clock_->TimeInMilliseconds() +
219 (audio_ ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000220}
221
Erik Språng61be2a42015-04-27 13:32:52 +0200222bool RTCPSender::Sending() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200223 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
224 return sending_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000225}
226
Erik Språng61be2a42015-04-27 13:32:52 +0200227int32_t RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
228 bool sending) {
229 bool sendRTCPBye = false;
230 {
Erik Språng242e22b2015-05-11 10:17:43 +0200231 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000232
Erik Språng242e22b2015-05-11 10:17:43 +0200233 if (method_ != kRtcpOff) {
234 if (sending == false && sending_ == true) {
Erik Språng61be2a42015-04-27 13:32:52 +0200235 // Trigger RTCP bye
236 sendRTCPBye = true;
237 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000238 }
Erik Språng242e22b2015-05-11 10:17:43 +0200239 sending_ = sending;
Erik Språng61be2a42015-04-27 13:32:52 +0200240 }
241 if (sendRTCPBye)
242 return SendRTCP(feedback_state, kRtcpBye);
243 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000244}
245
Erik Språng61be2a42015-04-27 13:32:52 +0200246bool RTCPSender::REMB() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200247 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
248 return remb_enabled_;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000249}
250
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000251void RTCPSender::SetREMBStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200252 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
253 remb_enabled_ = enable;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000254}
255
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000256void RTCPSender::SetREMBData(uint32_t bitrate,
257 const std::vector<uint32_t>& ssrcs) {
Erik Språng242e22b2015-05-11 10:17:43 +0200258 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
259 remb_bitrate_ = bitrate;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000260 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000261
Erik Språng242e22b2015-05-11 10:17:43 +0200262 if (remb_enabled_)
263 SetFlag(kRtcpRemb, false);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000264 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
265 // throttled by the caller.
Erik Språng242e22b2015-05-11 10:17:43 +0200266 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000267}
268
Erik Språng61be2a42015-04-27 13:32:52 +0200269bool RTCPSender::TMMBR() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200270 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
271 return IsFlagPresent(RTCPPacketType::kRtcpTmmbr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000272}
273
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000274void RTCPSender::SetTMMBRStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200275 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
276 if (enable) {
277 SetFlag(RTCPPacketType::kRtcpTmmbr, false);
278 } else {
279 ConsumeFlag(RTCPPacketType::kRtcpTmmbr, true);
280 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000281}
282
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000283void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
Erik Språng242e22b2015-05-11 10:17:43 +0200284 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000285 start_timestamp_ = start_timestamp;
286}
287
288void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
289 int64_t capture_time_ms) {
Erik Språng242e22b2015-05-11 10:17:43 +0200290 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000291 last_rtp_timestamp_ = rtp_timestamp;
292 if (capture_time_ms < 0) {
293 // We don't currently get a capture time from VoiceEngine.
Erik Språng242e22b2015-05-11 10:17:43 +0200294 last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000295 } else {
296 last_frame_capture_time_ms_ = capture_time_ms;
297 }
298}
299
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000300void RTCPSender::SetSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200301 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000302
Erik Språng242e22b2015-05-11 10:17:43 +0200303 if (ssrc_ != 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200304 // not first SetSSRC, probably due to a collision
305 // schedule a new RTCP report
306 // make sure that we send a RTP packet
Erik Språng242e22b2015-05-11 10:17:43 +0200307 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
Erik Språng61be2a42015-04-27 13:32:52 +0200308 }
Erik Språng242e22b2015-05-11 10:17:43 +0200309 ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000310}
311
Erik Språng61be2a42015-04-27 13:32:52 +0200312void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200313 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
314 remote_ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000315}
316
Peter Boström9ba52f82015-06-01 14:12:28 +0200317int32_t RTCPSender::SetCNAME(const char* c_name) {
318 if (!c_name)
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000319 return -1;
320
Peter Boström9ba52f82015-06-01 14:12:28 +0200321 DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
Erik Språng242e22b2015-05-11 10:17:43 +0200322 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200323 cname_ = c_name;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000324 return 0;
325}
326
Erik Språng0ea42d32015-06-25 14:46:16 +0200327int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC, const char* c_name) {
328 assert(c_name);
329 DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
Erik Språng242e22b2015-05-11 10:17:43 +0200330 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200331 if (csrc_cnames_.size() >= kRtpCsrcSize)
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000332 return -1;
Erik Språng0ea42d32015-06-25 14:46:16 +0200333
334 csrc_cnames_[SSRC] = c_name;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000335 return 0;
336}
337
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000338int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
Erik Språng242e22b2015-05-11 10:17:43 +0200339 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200340 auto it = csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000341
Erik Språng242e22b2015-05-11 10:17:43 +0200342 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000343 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200344
Erik Språng242e22b2015-05-11 10:17:43 +0200345 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000346 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000347}
348
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000349bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
niklase@google.com470e71d2011-07-07 08:21:25 +0000350/*
351 For audio we use a fix 5 sec interval
352
353 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000354 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
355 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000356
357
358From RFC 3550
359
360 MAX RTCP BW is 5% if the session BW
361 A send report is approximately 65 bytes inc CNAME
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000362 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000363
364 The RECOMMENDED value for the reduced minimum in seconds is 360
365 divided by the session bandwidth in kilobits/second. This minimum
366 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
367
368 If the participant has not yet sent an RTCP packet (the variable
369 initial is true), the constant Tmin is set to 2.5 seconds, else it
370 is set to 5 seconds.
371
372 The interval between RTCP packets is varied randomly over the
373 range [0.5,1.5] times the calculated interval to avoid unintended
374 synchronization of all participants
375
376 if we send
377 If the participant is a sender (we_sent true), the constant C is
378 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
379 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
380 number of senders.
381
382 if we receive only
383 If we_sent is not true, the constant C is set
384 to the average RTCP packet size divided by 75% of the RTCP
385 bandwidth. The constant n is set to the number of receivers
386 (members - senders). If the number of senders is greater than
387 25%, senders and receivers are treated together.
388
389 reconsideration NOT required for peer-to-peer
390 "timer reconsideration" is
391 employed. This algorithm implements a simple back-off mechanism
392 which causes users to hold back RTCP packet transmission if the
393 group sizes are increasing.
394
395 n = number of members
396 C = avg_size/(rtcpBW/4)
397
398 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
399
400 4. The calculated interval T is set to a number uniformly distributed
401 between 0.5 and 1.5 times the deterministic calculated interval.
402
403 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
404 for the fact that the timer reconsideration algorithm converges to
405 a value of the RTCP bandwidth below the intended average
406*/
407
Erik Språng242e22b2015-05-11 10:17:43 +0200408 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000409
Erik Språng242e22b2015-05-11 10:17:43 +0200410 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
xians@webrtc.org8738d272011-11-25 13:43:53 +0000411
Erik Språng242e22b2015-05-11 10:17:43 +0200412 if (method_ == kRtcpOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000413 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000414
Erik Språng242e22b2015-05-11 10:17:43 +0200415 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200416 // for video key-frames we want to send the RTCP before the large key-frame
417 // if we have a 100 ms margin
418 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
419 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000420
Erik Språng242e22b2015-05-11 10:17:43 +0200421 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200422 return true;
423 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200424 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200425 // wrap
426 return true;
427 }
428 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000429}
430
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000431int64_t RTCPSender::SendTimeOfSendReport(uint32_t sendReport) {
Erik Språng242e22b2015-05-11 10:17:43 +0200432 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000433
Erik Språng61be2a42015-04-27 13:32:52 +0200434 // This is only saved when we are the sender
Erik Språng242e22b2015-05-11 10:17:43 +0200435 if ((last_send_report_[0] == 0) || (sendReport == 0)) {
Erik Språng61be2a42015-04-27 13:32:52 +0200436 return 0; // will be ignored
437 } else {
438 for (int i = 0; i < RTCP_NUMBER_OF_SR; ++i) {
Erik Språng242e22b2015-05-11 10:17:43 +0200439 if (last_send_report_[i] == sendReport)
440 return last_rtcp_time_[i];
niklase@google.com470e71d2011-07-07 08:21:25 +0000441 }
Erik Språng61be2a42015-04-27 13:32:52 +0200442 }
443 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000444}
445
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000446bool RTCPSender::SendTimeOfXrRrReport(uint32_t mid_ntp,
447 int64_t* time_ms) const {
Erik Språng242e22b2015-05-11 10:17:43 +0200448 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000449
450 if (last_xr_rr_.empty()) {
451 return false;
452 }
453 std::map<uint32_t, int64_t>::const_iterator it = last_xr_rr_.find(mid_ntp);
454 if (it == last_xr_rr_.end()) {
455 return false;
456 }
457 *time_ms = it->second;
458 return true;
459}
460
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200461int32_t RTCPSender::AddReportBlock(const RTCPReportBlock& report_block) {
462 if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000463 LOG(LS_WARNING) << "Too many report blocks.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000464 return -1;
465 }
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200466 rtcp::ReportBlock* block = &report_blocks_[report_block.remoteSSRC];
467 block->To(report_block.remoteSSRC);
468 block->WithFractionLost(report_block.fractionLost);
469 block->WithCumulativeLost(report_block.cumulativeLost);
470 block->WithExtHighestSeqNum(report_block.extendedHighSeqNum);
471 block->WithJitter(report_block.jitter);
472 block->WithLastSr(report_block.lastSR);
473 block->WithDelayLastSr(report_block.delaySinceLastSR);
474
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000475 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000476}
477
Erik Språng242e22b2015-05-11 10:17:43 +0200478RTCPSender::BuildResult RTCPSender::BuildSR(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200479 for (int i = (RTCP_NUMBER_OF_SR - 2); i >= 0; i--) {
480 // shift old
Erik Språng242e22b2015-05-11 10:17:43 +0200481 last_send_report_[i + 1] = last_send_report_[i];
482 last_rtcp_time_[i + 1] = last_rtcp_time_[i];
Erik Språng61be2a42015-04-27 13:32:52 +0200483 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000484
Erik Språng242e22b2015-05-11 10:17:43 +0200485 last_rtcp_time_[0] = Clock::NtpToMs(ctx->ntp_sec, ctx->ntp_frac);
486 last_send_report_[0] = (ctx->ntp_sec << 16) + (ctx->ntp_frac >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000487
Erik Språng61be2a42015-04-27 13:32:52 +0200488 // The timestamp of this RTCP packet should be estimated as the timestamp of
489 // the frame being captured at this moment. We are calculating that
490 // timestamp as the last frame's timestamp + the time since the last frame
491 // was captured.
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200492 uint32_t rtp_timestamp =
493 start_timestamp_ + last_rtp_timestamp_ +
494 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) *
495 (ctx->feedback_state.frequency_hz / 1000);
niklase@google.com470e71d2011-07-07 08:21:25 +0000496
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200497 rtcp::SenderReport report;
498 report.From(ssrc_);
499 report.WithNtpSec(ctx->ntp_sec);
500 report.WithNtpFrac(ctx->ntp_frac);
501 report.WithRtpTimestamp(rtp_timestamp);
502 report.WithPacketCount(ctx->feedback_state.packets_sent);
503 report.WithOctetCount(ctx->feedback_state.media_bytes_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000504
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200505 for (auto it : report_blocks_)
506 report.WithReportBlock(it.second);
niklase@google.com470e71d2011-07-07 08:21:25 +0000507
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200508 PacketBuiltCallback callback(ctx);
Erik Språng72aa9a62015-07-31 16:16:02 +0200509 if (!callback.BuildPacket(report))
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200510 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000511
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200512 report_blocks_.clear();
Erik Språng242e22b2015-05-11 10:17:43 +0200513 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000514}
515
Erik Språng0ea42d32015-06-25 14:46:16 +0200516RTCPSender::BuildResult RTCPSender::BuildSDES(RtcpContext* ctx) {
517 size_t length_cname = cname_.length();
518 CHECK_LT(length_cname, static_cast<size_t>(RTCP_CNAME_SIZE));
niklase@google.com470e71d2011-07-07 08:21:25 +0000519
Erik Språng0ea42d32015-06-25 14:46:16 +0200520 rtcp::Sdes sdes;
521 sdes.WithCName(ssrc_, cname_);
522
523 for (const auto it : csrc_cnames_)
524 sdes.WithCName(it.first, it.second);
525
526 PacketBuiltCallback callback(ctx);
Erik Språng72aa9a62015-07-31 16:16:02 +0200527 if (!callback.BuildPacket(sdes))
Erik Språng242e22b2015-05-11 10:17:43 +0200528 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000529
Erik Språng242e22b2015-05-11 10:17:43 +0200530 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000531}
532
Erik Språng242e22b2015-05-11 10:17:43 +0200533RTCPSender::BuildResult RTCPSender::BuildRR(RtcpContext* ctx) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200534 rtcp::ReceiverReport report;
535 report.From(ssrc_);
536 for (auto it : report_blocks_)
537 report.WithReportBlock(it.second);
538
539 PacketBuiltCallback callback(ctx);
Erik Språng72aa9a62015-07-31 16:16:02 +0200540 if (!callback.BuildPacket(report))
Erik Språng242e22b2015-05-11 10:17:43 +0200541 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200542
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200543 report_blocks_.clear();
Erik Språng242e22b2015-05-11 10:17:43 +0200544
545 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000546}
547
Erik Språng242e22b2015-05-11 10:17:43 +0200548RTCPSender::BuildResult RTCPSender::BuildPLI(RtcpContext* ctx) {
Erik Språng72aa9a62015-07-31 16:16:02 +0200549 rtcp::Pli pli;
550 pli.From(ssrc_);
551 pli.To(remote_ssrc_);
552
553 PacketBuiltCallback callback(ctx);
554 if (!callback.BuildPacket(pli))
Erik Språng242e22b2015-05-11 10:17:43 +0200555 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200556
Erik Språng242e22b2015-05-11 10:17:43 +0200557 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
558 "RTCPSender::PLI");
559 ++packet_type_counter_.pli_packets;
560 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
561 ssrc_, packet_type_counter_.pli_packets);
562
563 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +0200564}
565
Erik Språng242e22b2015-05-11 10:17:43 +0200566RTCPSender::BuildResult RTCPSender::BuildFIR(RtcpContext* ctx) {
Erik Språng242e22b2015-05-11 10:17:43 +0200567 if (!ctx->repeat)
sprang62dae192015-08-05 02:35:35 -0700568 ++sequence_number_fir_; // Do not increase if repetition.
niklase@google.com470e71d2011-07-07 08:21:25 +0000569
sprang62dae192015-08-05 02:35:35 -0700570 rtcp::Fir fir;
571 fir.From(ssrc_);
572 fir.To(remote_ssrc_);
573 fir.WithCommandSeqNum(sequence_number_fir_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000574
sprang62dae192015-08-05 02:35:35 -0700575 PacketBuiltCallback callback(ctx);
576 if (!callback.BuildPacket(fir))
577 return BuildResult::kTruncated;
Erik Språng242e22b2015-05-11 10:17:43 +0200578
579 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
580 "RTCPSender::FIR");
581 ++packet_type_counter_.fir_packets;
582 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
583 ssrc_, packet_type_counter_.fir_packets);
584
585 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000586}
587
588/*
589 0 1 2 3
590 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
591 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
592 | First | Number | PictureID |
593 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
594*/
Erik Språng242e22b2015-05-11 10:17:43 +0200595RTCPSender::BuildResult RTCPSender::BuildSLI(RtcpContext* ctx) {
sprang0365a272015-08-11 01:02:37 -0700596 rtcp::Sli sli;
597 sli.From(ssrc_);
598 sli.To(remote_ssrc_);
599 // Crop picture id to 6 least significant bits.
600 sli.WithPictureId(ctx->picture_id & 0x3F);
601 sli.WithFirstMb(0);
602 sli.WithNumberOfMb(0x1FFF); // 13 bits, only ones for now.
603
604 PacketBuiltCallback callback(ctx);
605 if (!callback.BuildPacket(sli))
Erik Språng242e22b2015-05-11 10:17:43 +0200606 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000607
Erik Språng242e22b2015-05-11 10:17:43 +0200608 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000609}
610
611/*
612 0 1 2 3
613 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
614 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
615 | PB |0| Payload Type| Native RPSI bit string |
616 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
617 | defined per codec ... | Padding (0) |
618 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
619*/
620/*
621* Note: not generic made for VP8
622*/
Erik Språng242e22b2015-05-11 10:17:43 +0200623RTCPSender::BuildResult RTCPSender::BuildRPSI(RtcpContext* ctx) {
624 if (ctx->feedback_state.send_payload_type == 0xFF)
625 return BuildResult::kError;
626
sprangcf7f54d2015-08-13 04:37:42 -0700627 rtcp::Rpsi rpsi;
628 rpsi.From(ssrc_);
629 rpsi.To(remote_ssrc_);
630 rpsi.WithPayloadType(ctx->feedback_state.send_payload_type);
631 rpsi.WithPictureId(ctx->picture_id);
632
633 PacketBuiltCallback callback(ctx);
634 if (!callback.BuildPacket(rpsi))
Erik Språng242e22b2015-05-11 10:17:43 +0200635 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000636
Erik Språng242e22b2015-05-11 10:17:43 +0200637 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000638}
639
Erik Språng242e22b2015-05-11 10:17:43 +0200640RTCPSender::BuildResult RTCPSender::BuildREMB(RtcpContext* ctx) {
sprangdd4edc52015-08-21 04:21:51 -0700641 rtcp::Remb remb;
642 remb.From(ssrc_);
643 for (uint32_t ssrc : remb_ssrcs_)
644 remb.AppliesTo(ssrc);
645 remb.WithBitrateBps(remb_bitrate_);
646
647 PacketBuiltCallback callback(ctx);
648 if (!callback.BuildPacket(remb))
Erik Språng242e22b2015-05-11 10:17:43 +0200649 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200650
Erik Språng242e22b2015-05-11 10:17:43 +0200651 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
652 "RTCPSender::REMB");
653
654 return BuildResult::kSuccess;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000655}
656
Erik Språng61be2a42015-04-27 13:32:52 +0200657void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
Erik Språng242e22b2015-05-11 10:17:43 +0200658 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
659 tmmbr_send_ = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000660}
661
Erik Språng242e22b2015-05-11 10:17:43 +0200662RTCPSender::BuildResult RTCPSender::BuildTMMBR(RtcpContext* ctx) {
663 if (ctx->feedback_state.module == NULL)
664 return BuildResult::kError;
Erik Språng61be2a42015-04-27 13:32:52 +0200665 // Before sending the TMMBR check the received TMMBN, only an owner is
666 // allowed to raise the bitrate:
667 // * If the sender is an owner of the TMMBN -> send TMMBR
668 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000669
Erik Språng61be2a42015-04-27 13:32:52 +0200670 // get current bounding set from RTCP receiver
671 bool tmmbrOwner = false;
672 // store in candidateSet, allocates one extra slot
Erik Språng242e22b2015-05-11 10:17:43 +0200673 TMMBRSet* candidateSet = tmmbr_help_.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000674
Erik Språng242e22b2015-05-11 10:17:43 +0200675 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
676 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
Erik Språng61be2a42015-04-27 13:32:52 +0200677 // since RTCPreceiver is not doing the reverse we should be fine
678 int32_t lengthOfBoundingSet =
Erik Språng242e22b2015-05-11 10:17:43 +0200679 ctx->feedback_state.module->BoundingSet(tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +0000680
Erik Språng61be2a42015-04-27 13:32:52 +0200681 if (lengthOfBoundingSet > 0) {
682 for (int32_t i = 0; i < lengthOfBoundingSet; i++) {
Erik Språng242e22b2015-05-11 10:17:43 +0200683 if (candidateSet->Tmmbr(i) == tmmbr_send_ &&
684 candidateSet->PacketOH(i) == packet_oh_send_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200685 // do not send the same tuple
Erik Språng242e22b2015-05-11 10:17:43 +0200686 return BuildResult::kAborted;
Erik Språng61be2a42015-04-27 13:32:52 +0200687 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000688 }
Erik Språng61be2a42015-04-27 13:32:52 +0200689 if (!tmmbrOwner) {
690 // use received bounding set as candidate set
691 // add current tuple
Erik Språng242e22b2015-05-11 10:17:43 +0200692 candidateSet->SetEntry(lengthOfBoundingSet, tmmbr_send_, packet_oh_send_,
693 ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200694 int numCandidates = lengthOfBoundingSet + 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000695
Erik Språng61be2a42015-04-27 13:32:52 +0200696 // find bounding set
697 TMMBRSet* boundingSet = NULL;
Erik Språng242e22b2015-05-11 10:17:43 +0200698 int numBoundingSet = tmmbr_help_.FindTMMBRBoundingSet(boundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200699 if (numBoundingSet > 0 || numBoundingSet <= numCandidates)
Erik Språng242e22b2015-05-11 10:17:43 +0200700 tmmbrOwner = tmmbr_help_.IsOwner(ssrc_, numBoundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200701 if (!tmmbrOwner) {
702 // did not enter bounding set, no meaning to send this request
Erik Språng242e22b2015-05-11 10:17:43 +0200703 return BuildResult::kAborted;
Erik Språng61be2a42015-04-27 13:32:52 +0200704 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000705 }
Erik Språng61be2a42015-04-27 13:32:52 +0200706 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000707
Erik Språng242e22b2015-05-11 10:17:43 +0200708 if (tmmbr_send_) {
sprang81a3e602015-08-21 05:30:11 -0700709 rtcp::Tmmbr tmmbr;
710 tmmbr.From(ssrc_);
711 tmmbr.To(remote_ssrc_);
712 tmmbr.WithBitrateKbps(tmmbr_send_);
713 tmmbr.WithOverhead(packet_oh_send_);
714
715 PacketBuiltCallback callback(ctx);
716 if (!callback.BuildPacket(tmmbr))
Erik Språng242e22b2015-05-11 10:17:43 +0200717 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200718 }
Erik Språng242e22b2015-05-11 10:17:43 +0200719 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +0200720}
721
Erik Språng242e22b2015-05-11 10:17:43 +0200722RTCPSender::BuildResult RTCPSender::BuildTMMBN(RtcpContext* ctx) {
723 TMMBRSet* boundingSet = tmmbr_help_.BoundingSetToSend();
Erik Språng61be2a42015-04-27 13:32:52 +0200724 if (boundingSet == NULL)
Erik Språng242e22b2015-05-11 10:17:43 +0200725 return BuildResult::kError;
Erik Språng61be2a42015-04-27 13:32:52 +0200726
sprangd83df502015-08-27 01:05:08 -0700727 rtcp::Tmmbn tmmbn;
728 tmmbn.From(ssrc_);
729 for (uint32_t i = 0; i < boundingSet->lengthOfSet(); i++) {
730 if (boundingSet->Tmmbr(i) > 0) {
731 tmmbn.WithTmmbr(boundingSet->Ssrc(i), boundingSet->Tmmbr(i),
732 boundingSet->PacketOH(i));
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000733 }
Erik Språng61be2a42015-04-27 13:32:52 +0200734 }
sprangd83df502015-08-27 01:05:08 -0700735
736 PacketBuiltCallback callback(ctx);
737 if (!callback.BuildPacket(tmmbn))
738 return BuildResult::kTruncated;
Erik Språng242e22b2015-05-11 10:17:43 +0200739
740 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000741}
742
Erik Språng242e22b2015-05-11 10:17:43 +0200743RTCPSender::BuildResult RTCPSender::BuildAPP(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200744 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200745 if (app_data_ == NULL) {
Erik Språng61be2a42015-04-27 13:32:52 +0200746 LOG(LS_WARNING) << "Failed to build app specific.";
Erik Språng242e22b2015-05-11 10:17:43 +0200747 return BuildResult::kError;
Erik Språng61be2a42015-04-27 13:32:52 +0200748 }
Erik Språng242e22b2015-05-11 10:17:43 +0200749 if (ctx->position + 12 + app_length_ >= IP_PACKET_SIZE) {
Erik Språng61be2a42015-04-27 13:32:52 +0200750 LOG(LS_WARNING) << "Failed to build app specific.";
Erik Språng242e22b2015-05-11 10:17:43 +0200751 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200752 }
Erik Språng242e22b2015-05-11 10:17:43 +0200753 *ctx->AllocateData(1) = 0x80 + app_sub_type_;
Erik Språng61be2a42015-04-27 13:32:52 +0200754
755 // Add APP ID
Erik Språng242e22b2015-05-11 10:17:43 +0200756 *ctx->AllocateData(1) = 204;
Erik Språng61be2a42015-04-27 13:32:52 +0200757
Erik Språng242e22b2015-05-11 10:17:43 +0200758 uint16_t length = (app_length_ >> 2) + 2; // include SSRC and name
759 *ctx->AllocateData(1) = static_cast<uint8_t>(length >> 8);
760 *ctx->AllocateData(1) = static_cast<uint8_t>(length);
Erik Språng61be2a42015-04-27 13:32:52 +0200761
762 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200763 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200764
765 // Add our application name
Erik Språng242e22b2015-05-11 10:17:43 +0200766 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), app_name_);
Erik Språng61be2a42015-04-27 13:32:52 +0200767
768 // Add the data
Erik Språng242e22b2015-05-11 10:17:43 +0200769 memcpy(ctx->AllocateData(app_length_), app_data_.get(), app_length_);
770
771 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +0200772}
773
Erik Språng242e22b2015-05-11 10:17:43 +0200774RTCPSender::BuildResult RTCPSender::BuildNACK(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200775 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200776 if (ctx->position + 16 >= IP_PACKET_SIZE) {
Erik Språng61be2a42015-04-27 13:32:52 +0200777 LOG(LS_WARNING) << "Failed to build NACK.";
Erik Språng242e22b2015-05-11 10:17:43 +0200778 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200779 }
780
Erik Språng242e22b2015-05-11 10:17:43 +0200781 // int size, uint16_t* nack_list
Erik Språng61be2a42015-04-27 13:32:52 +0200782 // add nack list
783 uint8_t FMT = 1;
Erik Språng242e22b2015-05-11 10:17:43 +0200784 *ctx->AllocateData(1) = 0x80 + FMT;
785 *ctx->AllocateData(1) = 205;
Erik Språng61be2a42015-04-27 13:32:52 +0200786
Erik Språng242e22b2015-05-11 10:17:43 +0200787 *ctx->AllocateData(1) = 0;
788 int nack_size_pos_ = ctx->position;
789 *ctx->AllocateData(1) = 3; // setting it to one kNACK signal as default
Erik Språng61be2a42015-04-27 13:32:52 +0200790
791 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200792 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200793
794 // Add the remote SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200795 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200796
797 // Build NACK bitmasks and write them to the RTCP message.
798 // The nack list should be sorted and not contain duplicates if one
799 // wants to build the smallest rtcp nack packet.
800 int numOfNackFields = 0;
801 int maxNackFields =
Erik Språng242e22b2015-05-11 10:17:43 +0200802 std::min<int>(kRtcpMaxNackFields, (IP_PACKET_SIZE - ctx->position) / 4);
Erik Språng61be2a42015-04-27 13:32:52 +0200803 int i = 0;
Erik Språng242e22b2015-05-11 10:17:43 +0200804 while (i < ctx->nack_size && numOfNackFields < maxNackFields) {
805 uint16_t nack = ctx->nack_list[i++];
Erik Språng61be2a42015-04-27 13:32:52 +0200806 uint16_t bitmask = 0;
Erik Språng242e22b2015-05-11 10:17:43 +0200807 while (i < ctx->nack_size) {
808 int shift = static_cast<uint16_t>(ctx->nack_list[i] - nack) - 1;
Erik Språng61be2a42015-04-27 13:32:52 +0200809 if (shift >= 0 && shift <= 15) {
810 bitmask |= (1 << shift);
811 ++i;
812 } else {
813 break;
814 }
815 }
816 // Write the sequence number and the bitmask to the packet.
Erik Språng242e22b2015-05-11 10:17:43 +0200817 assert(ctx->position + 4 < IP_PACKET_SIZE);
818 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2), nack);
819 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2), bitmask);
Erik Språng61be2a42015-04-27 13:32:52 +0200820 numOfNackFields++;
821 }
Erik Språng242e22b2015-05-11 10:17:43 +0200822 ctx->buffer[nack_size_pos_] = static_cast<uint8_t>(2 + numOfNackFields);
Erik Språng61be2a42015-04-27 13:32:52 +0200823
Erik Språng242e22b2015-05-11 10:17:43 +0200824 if (i != ctx->nack_size)
Erik Språng61be2a42015-04-27 13:32:52 +0200825 LOG(LS_WARNING) << "Nack list too large for one packet.";
826
827 // Report stats.
828 NACKStringBuilder stringBuilder;
829 for (int idx = 0; idx < i; ++idx) {
Erik Språng242e22b2015-05-11 10:17:43 +0200830 stringBuilder.PushNACK(ctx->nack_list[idx]);
831 nack_stats_.ReportRequest(ctx->nack_list[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +0200832 }
Erik Språng61be2a42015-04-27 13:32:52 +0200833 packet_type_counter_.nack_requests = nack_stats_.requests();
834 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +0200835
836 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
837 "RTCPSender::NACK", "nacks",
838 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
839 ++packet_type_counter_.nack_packets;
840 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
841 ssrc_, packet_type_counter_.nack_packets);
842
843 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +0200844}
845
Erik Språng242e22b2015-05-11 10:17:43 +0200846RTCPSender::BuildResult RTCPSender::BuildBYE(RtcpContext* ctx) {
sprangd8ee4f92015-08-24 03:25:19 -0700847 rtcp::Bye bye;
848 bye.From(ssrc_);
849 for (uint32_t csrc : csrcs_)
850 bye.WithCsrc(csrc);
851
852 PacketBuiltCallback callback(ctx);
853 if (!callback.BuildPacket(bye))
Erik Språng242e22b2015-05-11 10:17:43 +0200854 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000855
Erik Språng242e22b2015-05-11 10:17:43 +0200856 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000857}
858
Erik Språng242e22b2015-05-11 10:17:43 +0200859RTCPSender::BuildResult RTCPSender::BuildReceiverReferenceTime(
860 RtcpContext* ctx) {
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000861
Erik Språng61be2a42015-04-27 13:32:52 +0200862 if (last_xr_rr_.size() >= RTCP_NUMBER_OF_SR)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000863 last_xr_rr_.erase(last_xr_rr_.begin());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000864 last_xr_rr_.insert(std::pair<uint32_t, int64_t>(
Erik Språng242e22b2015-05-11 10:17:43 +0200865 RTCPUtility::MidNtp(ctx->ntp_sec, ctx->ntp_frac),
866 Clock::NtpToMs(ctx->ntp_sec, ctx->ntp_frac)));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000867
Erik Språngca28fdc2015-08-31 14:00:50 +0200868 rtcp::Xr xr;
869 xr.From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000870
Erik Språngca28fdc2015-08-31 14:00:50 +0200871 rtcp::Rrtr rrtr;
872 rrtr.WithNtpSec(ctx->ntp_sec);
873 rrtr.WithNtpFrac(ctx->ntp_frac);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000874
Erik Språngca28fdc2015-08-31 14:00:50 +0200875 xr.WithRrtr(&rrtr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000876
Erik Språngca28fdc2015-08-31 14:00:50 +0200877 // TODO(sprang): Merge XR report sending to contain all of RRTR, DLRR, VOIP?
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000878
Erik Språngca28fdc2015-08-31 14:00:50 +0200879 PacketBuiltCallback callback(ctx);
880 if (!callback.BuildPacket(xr))
881 return BuildResult::kTruncated;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000882
Erik Språng242e22b2015-05-11 10:17:43 +0200883 return BuildResult::kSuccess;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000884}
885
Erik Språng242e22b2015-05-11 10:17:43 +0200886RTCPSender::BuildResult RTCPSender::BuildDlrr(RtcpContext* ctx) {
Erik Språngca28fdc2015-08-31 14:00:50 +0200887 rtcp::Xr xr;
888 xr.From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000889
Erik Språngca28fdc2015-08-31 14:00:50 +0200890 rtcp::Dlrr dlrr;
Erik Språng242e22b2015-05-11 10:17:43 +0200891 const RtcpReceiveTimeInfo& info = ctx->feedback_state.last_xr_rr;
Erik Språngca28fdc2015-08-31 14:00:50 +0200892 dlrr.WithDlrrItem(info.sourceSSRC, info.lastRR, info.delaySinceLastRR);
893
894 xr.WithDlrr(&dlrr);
895
896 PacketBuiltCallback callback(ctx);
897 if (!callback.BuildPacket(xr))
898 return BuildResult::kTruncated;
Erik Språng242e22b2015-05-11 10:17:43 +0200899
900 return BuildResult::kSuccess;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000901}
902
Erik Språng242e22b2015-05-11 10:17:43 +0200903// TODO(sprang): Add a unit test for this, or remove if the code isn't used.
904RTCPSender::BuildResult RTCPSender::BuildVoIPMetric(RtcpContext* ctx) {
Erik Språngca28fdc2015-08-31 14:00:50 +0200905 rtcp::Xr xr;
906 xr.From(ssrc_);
907
908 rtcp::VoipMetric voip;
909 voip.To(remote_ssrc_);
910 voip.LossRate(xr_voip_metric_.lossRate);
911 voip.DiscardRate(xr_voip_metric_.discardRate);
912 voip.BurstDensity(xr_voip_metric_.burstDensity);
913 voip.GapDensity(xr_voip_metric_.gapDensity);
914 voip.BurstDuration(xr_voip_metric_.burstDuration);
915 voip.GapDuration(xr_voip_metric_.gapDuration);
916 voip.RoundTripDelay(xr_voip_metric_.roundTripDelay);
917 voip.EndSystemDelay(xr_voip_metric_.endSystemDelay);
918 voip.SignalLevel(xr_voip_metric_.signalLevel);
919 voip.NoiseLevel(xr_voip_metric_.noiseLevel);
920 voip.Rerl(xr_voip_metric_.RERL);
921 voip.Gmin(xr_voip_metric_.Gmin);
922 voip.Rfactor(xr_voip_metric_.Rfactor);
923 voip.ExtRfactor(xr_voip_metric_.extRfactor);
924 voip.MosLq(xr_voip_metric_.MOSLQ);
925 voip.MosCq(xr_voip_metric_.MOSCQ);
926 voip.RxConfig(xr_voip_metric_.RXconfig);
927 voip.JbNominal(xr_voip_metric_.JBnominal);
928 voip.JbMax(xr_voip_metric_.JBmax);
929 voip.JbAbsMax(xr_voip_metric_.JBabsMax);
930
931 xr.WithVoipMetric(&voip);
932
933 PacketBuiltCallback callback(ctx);
934 if (!callback.BuildPacket(xr))
Erik Språng242e22b2015-05-11 10:17:43 +0200935 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000936
Erik Språng242e22b2015-05-11 10:17:43 +0200937 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000938}
939
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000940int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200941 RTCPPacketType packetType,
942 int32_t nack_size,
943 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000944 bool repeat,
945 uint64_t pictureID) {
Erik Språng242e22b2015-05-11 10:17:43 +0200946 return SendCompoundRTCP(
947 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
948 nack_size, nack_list, repeat, pictureID);
949}
950
951int32_t RTCPSender::SendCompoundRTCP(
952 const FeedbackState& feedback_state,
953 const std::set<RTCPPacketType>& packetTypes,
954 int32_t nack_size,
955 const uint16_t* nack_list,
956 bool repeat,
957 uint64_t pictureID) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000958 {
Erik Språng242e22b2015-05-11 10:17:43 +0200959 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
960 if (method_ == kRtcpOff) {
Erik Språng61be2a42015-04-27 13:32:52 +0200961 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
962 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +0000963 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000964 }
965 uint8_t rtcp_buffer[IP_PACKET_SIZE];
Erik Språng242e22b2015-05-11 10:17:43 +0200966 int rtcp_length =
967 PrepareRTCP(feedback_state, packetTypes, nack_size, nack_list, repeat,
968 pictureID, rtcp_buffer, IP_PACKET_SIZE);
Erik Språng61be2a42015-04-27 13:32:52 +0200969
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000970 // Sanity don't send empty packets.
Erik Språng242e22b2015-05-11 10:17:43 +0200971 if (rtcp_length <= 0)
972 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200973
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000974 return SendToNetwork(rtcp_buffer, static_cast<size_t>(rtcp_length));
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000975}
976
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000977int RTCPSender::PrepareRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200978 const std::set<RTCPPacketType>& packetTypes,
979 int32_t nack_size,
980 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000981 bool repeat,
982 uint64_t pictureID,
983 uint8_t* rtcp_buffer,
984 int buffer_size) {
Erik Språng242e22b2015-05-11 10:17:43 +0200985 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000986
Erik Språng242e22b2015-05-11 10:17:43 +0200987 RtcpContext context(feedback_state, nack_size, nack_list, repeat, pictureID,
988 rtcp_buffer, buffer_size);
989
990 // Add all flags as volatile. Non volatile entries will not be overwritten
991 // and all new volatile flags added will be consumed by the end of this call.
992 SetFlags(packetTypes, true);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000993
Erik Språng61be2a42015-04-27 13:32:52 +0200994 if (packet_type_counter_.first_packet_time_ms == -1)
Erik Språng242e22b2015-05-11 10:17:43 +0200995 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språng61be2a42015-04-27 13:32:52 +0200996
Erik Språng242e22b2015-05-11 10:17:43 +0200997 bool generate_report;
998 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
999 // Report type already explicitly set, don't automatically populate.
1000 generate_report = true;
1001 DCHECK(ConsumeFlag(kRtcpReport) == false);
1002 } else {
1003 generate_report =
1004 (ConsumeFlag(kRtcpReport) && method_ == kRtcpNonCompound) ||
1005 method_ == kRtcpCompound;
1006 if (generate_report)
1007 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +00001008 }
1009
Erik Språng0ea42d32015-06-25 14:46:16 +02001010 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
Erik Språng242e22b2015-05-11 10:17:43 +02001011 SetFlag(kRtcpSdes, true);
1012
1013 // We need to send our NTP even if we haven't received any reports.
1014 clock_->CurrentNtp(context.ntp_sec, context.ntp_frac);
1015
1016 if (generate_report) {
1017 if (!sending_ && xr_send_receiver_reference_time_enabled_)
1018 SetFlag(kRtcpXrReceiverReferenceTime, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001019 if (feedback_state.has_last_xr_rr)
Erik Språng242e22b2015-05-11 10:17:43 +02001020 SetFlag(kRtcpXrDlrrReportBlock, true);
1021
1022 // generate next time to send an RTCP report
Erik Språng61be2a42015-04-27 13:32:52 +02001023 // seeded from RTP constructor
1024 int32_t random = rand() % 1000;
1025 int32_t timeToNext = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001026
Erik Språng242e22b2015-05-11 10:17:43 +02001027 if (audio_) {
Erik Språng61be2a42015-04-27 13:32:52 +02001028 timeToNext = (RTCP_INTERVAL_AUDIO_MS / 2) +
1029 (RTCP_INTERVAL_AUDIO_MS * random / 1000);
1030 } else {
1031 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
Erik Språng242e22b2015-05-11 10:17:43 +02001032 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +02001033 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
1034 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
1035 if (send_bitrate_kbit != 0)
1036 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001037 }
Erik Språng61be2a42015-04-27 13:32:52 +02001038 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
1039 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
1040 timeToNext = (minIntervalMs / 2) + (minIntervalMs * random / 1000);
1041 }
Erik Språng242e22b2015-05-11 10:17:43 +02001042 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001043
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001044 StatisticianMap statisticians =
1045 receive_statistics_->GetActiveStatisticians();
1046 if (!statisticians.empty()) {
Erik Språng61be2a42015-04-27 13:32:52 +02001047 for (auto it = statisticians.begin(); it != statisticians.end(); ++it) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001048 RTCPReportBlock report_block;
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001049 if (PrepareReport(feedback_state, it->first, it->second,
1050 &report_block)) {
1051 AddReportBlock(report_block);
Erik Språng61be2a42015-04-27 13:32:52 +02001052 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001053 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001054 }
1055 }
1056
Erik Språng242e22b2015-05-11 10:17:43 +02001057 auto it = report_flags_.begin();
1058 while (it != report_flags_.end()) {
1059 auto builder = builders_.find(it->type);
1060 DCHECK(builder != builders_.end());
1061 if (it->is_volatile) {
1062 report_flags_.erase(it++);
1063 } else {
1064 ++it;
Erik Språng61be2a42015-04-27 13:32:52 +02001065 }
Erik Språng242e22b2015-05-11 10:17:43 +02001066
1067 uint32_t start_position = context.position;
Erik Språng0ea42d32015-06-25 14:46:16 +02001068 BuildResult result = (this->*(builder->second))(&context);
Erik Språng242e22b2015-05-11 10:17:43 +02001069 switch (result) {
1070 case BuildResult::kError:
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001071 return -1;
Erik Språng242e22b2015-05-11 10:17:43 +02001072 case BuildResult::kTruncated:
1073 return context.position;
1074 case BuildResult::kAborted:
1075 context.position = start_position;
1076 FALLTHROUGH();
1077 case BuildResult::kSuccess:
1078 continue;
Erik Språng61be2a42015-04-27 13:32:52 +02001079 default:
Erik Språng242e22b2015-05-11 10:17:43 +02001080 abort();
Erik Språng61be2a42015-04-27 13:32:52 +02001081 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001082 }
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001083
1084 if (packet_type_counter_observer_ != NULL) {
1085 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
Erik Språng242e22b2015-05-11 10:17:43 +02001086 remote_ssrc_, packet_type_counter_);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001087 }
1088
Erik Språng242e22b2015-05-11 10:17:43 +02001089 DCHECK(AllVolatileFlagsConsumed());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001090
Erik Språng242e22b2015-05-11 10:17:43 +02001091 return context.position;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001092}
1093
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001094bool RTCPSender::PrepareReport(const FeedbackState& feedback_state,
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001095 uint32_t ssrc,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001096 StreamStatistician* statistician,
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001097 RTCPReportBlock* report_block) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001098 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +00001099 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001100 if (!statistician->GetStatistics(&stats, true))
1101 return false;
1102 report_block->fractionLost = stats.fraction_lost;
1103 report_block->cumulativeLost = stats.cumulative_lost;
1104 report_block->extendedHighSeqNum =
1105 stats.extended_max_sequence_number;
1106 report_block->jitter = stats.jitter;
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001107 report_block->remoteSSRC = ssrc;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001108
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001109 // TODO(sprang): Do we really need separate time stamps for each report?
1110 // Get our NTP as late as possible to avoid a race.
1111 uint32_t ntp_secs;
1112 uint32_t ntp_frac;
1113 clock_->CurrentNtp(ntp_secs, ntp_frac);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001114
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001115 // Delay since last received report.
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001116 uint32_t delaySinceLastReceivedSR = 0;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001117 if ((feedback_state.last_rr_ntp_secs != 0) ||
1118 (feedback_state.last_rr_ntp_frac != 0)) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001119 // Get the 16 lowest bits of seconds and the 16 highest bits of fractions.
1120 uint32_t now = ntp_secs & 0x0000FFFF;
Erik Språng61be2a42015-04-27 13:32:52 +02001121 now <<= 16;
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001122 now += (ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001123
Erik Språng61be2a42015-04-27 13:32:52 +02001124 uint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
1125 receiveTime <<= 16;
1126 receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001127
1128 delaySinceLastReceivedSR = now-receiveTime;
1129 }
1130 report_block->delaySinceLastSR = delaySinceLastReceivedSR;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001131 report_block->lastSR = feedback_state.remote_sr;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001132 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +00001133}
1134
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001135int32_t RTCPSender::SendToNetwork(const uint8_t* dataBuffer, size_t length) {
Erik Språng242e22b2015-05-11 10:17:43 +02001136 CriticalSectionScoped lock(critical_section_transport_.get());
1137 if (cbTransport_) {
1138 if (cbTransport_->SendRTCPPacket(id_, dataBuffer, length) > 0)
Erik Språng61be2a42015-04-27 13:32:52 +02001139 return 0;
1140 }
1141 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001142}
1143
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001144void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
1145 assert(csrcs.size() <= kRtpCsrcSize);
Erik Språng242e22b2015-05-11 10:17:43 +02001146 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001147 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +00001148}
1149
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001150int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
1151 uint32_t name,
1152 const uint8_t* data,
1153 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +02001154 if (length % 4 != 0) {
1155 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
1156 return -1;
1157 }
Erik Språng242e22b2015-05-11 10:17:43 +02001158 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +00001159
Erik Språng242e22b2015-05-11 10:17:43 +02001160 SetFlag(kRtcpApp, true);
1161 app_sub_type_ = subType;
1162 app_name_ = name;
1163 app_data_.reset(new uint8_t[length]);
1164 app_length_ = length;
1165 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +02001166 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001167}
1168
Erik Språng61be2a42015-04-27 13:32:52 +02001169int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
Erik Språng242e22b2015-05-11 10:17:43 +02001170 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1171 memcpy(&xr_voip_metric_, VoIPMetric, sizeof(RTCPVoIPMetric));
niklase@google.com470e71d2011-07-07 08:21:25 +00001172
Erik Språng242e22b2015-05-11 10:17:43 +02001173 SetFlag(kRtcpXrVoipMetric, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001174 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001175}
1176
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001177void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +02001178 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1179 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001180}
1181
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00001182bool RTCPSender::RtcpXrReceiverReferenceTime() const {
Erik Språng242e22b2015-05-11 10:17:43 +02001183 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1184 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00001185}
1186
niklase@google.com470e71d2011-07-07 08:21:25 +00001187// no callbacks allowed inside this function
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001188int32_t RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
1189 uint32_t maxBitrateKbit) {
Erik Språng242e22b2015-05-11 10:17:43 +02001190 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +00001191
Erik Språng242e22b2015-05-11 10:17:43 +02001192 if (0 == tmmbr_help_.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit)) {
1193 SetFlag(kRtcpTmmbn, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001194 return 0;
1195 }
1196 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001197}
Erik Språng61be2a42015-04-27 13:32:52 +02001198
Erik Språng242e22b2015-05-11 10:17:43 +02001199void RTCPSender::SetFlag(RTCPPacketType type, bool is_volatile) {
1200 report_flags_.insert(ReportFlag(type, is_volatile));
1201}
1202
1203void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
1204 bool is_volatile) {
1205 for (RTCPPacketType type : types)
1206 SetFlag(type, is_volatile);
1207}
1208
1209bool RTCPSender::IsFlagPresent(RTCPPacketType type) const {
1210 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
1211}
1212
1213bool RTCPSender::ConsumeFlag(RTCPPacketType type, bool forced) {
1214 auto it = report_flags_.find(ReportFlag(type, false));
1215 if (it == report_flags_.end())
1216 return false;
1217 if (it->is_volatile || forced)
1218 report_flags_.erase((it));
1219 return true;
1220}
1221
1222bool RTCPSender::AllVolatileFlagsConsumed() const {
1223 for (const ReportFlag& flag : report_flags_) {
1224 if (flag.is_volatile)
1225 return false;
1226 }
1227 return true;
1228}
1229
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001230} // namespace webrtc