blob: 1b8c62faaf78d80be2e13fca78eb80b375e1005f [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000011#include "webrtc/modules/rtp_rtcp/source/rtcp_sender.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000013#include <assert.h> // assert
14#include <stdlib.h> // rand
stefan@webrtc.org9354cc92012-06-07 08:10:14 +000015#include <string.h> // memcpy
niklase@google.com470e71d2011-07-07 08:21:25 +000016
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000017#include <algorithm> // min
Erik Språng61be2a42015-04-27 13:32:52 +020018#include <limits> // max
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000019
Erik Språng61be2a42015-04-27 13:32:52 +020020#include "webrtc/base/checks.h"
Peter Boströmebc0b4e2015-10-28 16:39:33 +010021#include "webrtc/base/logging.h"
tommie4f96502015-10-20 23:00:48 -070022#include "webrtc/base/trace_event.h"
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000023#include "webrtc/common_types.h"
sprang@webrtc.org779c3d12015-03-17 16:42:49 +000024#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
sprang233bd872015-09-08 13:25:16 -070025#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
tommie4f96502015-10-20 23:00:48 -070026#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010027#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000028
niklase@google.com470e71d2011-07-07 08:21:25 +000029namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000030
31using RTCPUtility::RTCPCnameInformation;
32
Erik Språng61be2a42015-04-27 13:32:52 +020033NACKStringBuilder::NACKStringBuilder()
Erik Språng242e22b2015-05-11 10:17:43 +020034 : stream_(""), count_(0), prevNack_(0), consecutive_(false) {
edjee@google.com79b02892013-04-04 19:43:34 +000035}
36
pbos@webrtc.orgf3e4cee2013-07-31 15:17:19 +000037NACKStringBuilder::~NACKStringBuilder() {}
38
pbos@webrtc.org2f446732013-04-08 11:08:41 +000039void NACKStringBuilder::PushNACK(uint16_t nack)
edjee@google.com79b02892013-04-04 19:43:34 +000040{
Erik Språng242e22b2015-05-11 10:17:43 +020041 if (count_ == 0) {
42 stream_ << nack;
43 } else if (nack == prevNack_ + 1) {
44 consecutive_ = true;
Erik Språng61be2a42015-04-27 13:32:52 +020045 } else {
Erik Språng242e22b2015-05-11 10:17:43 +020046 if (consecutive_) {
47 stream_ << "-" << prevNack_;
48 consecutive_ = false;
edjee@google.com79b02892013-04-04 19:43:34 +000049 }
Erik Språng242e22b2015-05-11 10:17:43 +020050 stream_ << "," << nack;
Erik Språng61be2a42015-04-27 13:32:52 +020051 }
Erik Språng242e22b2015-05-11 10:17:43 +020052 count_++;
53 prevNack_ = nack;
edjee@google.com79b02892013-04-04 19:43:34 +000054}
55
Erik Språng61be2a42015-04-27 13:32:52 +020056std::string NACKStringBuilder::GetResult() {
Erik Språng242e22b2015-05-11 10:17:43 +020057 if (consecutive_) {
58 stream_ << "-" << prevNack_;
59 consecutive_ = false;
Erik Språng61be2a42015-04-27 13:32:52 +020060 }
Erik Språng242e22b2015-05-11 10:17:43 +020061 return stream_.str();
edjee@google.com79b02892013-04-04 19:43:34 +000062}
63
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000064RTCPSender::FeedbackState::FeedbackState()
65 : send_payload_type(0),
66 frequency_hz(0),
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +000067 packets_sent(0),
68 media_bytes_sent(0),
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000069 send_bitrate(0),
70 last_rr_ntp_secs(0),
71 last_rr_ntp_frac(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000072 remote_sr(0),
Erik Språng61be2a42015-04-27 13:32:52 +020073 has_last_xr_rr(false),
74 module(nullptr) {
75}
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000076
Erik Språng242e22b2015-05-11 10:17:43 +020077struct RTCPSender::RtcpContext {
78 RtcpContext(const FeedbackState& feedback_state,
79 int32_t nack_size,
80 const uint16_t* nack_list,
81 bool repeat,
82 uint64_t picture_id,
83 uint8_t* buffer,
84 uint32_t buffer_size)
85 : feedback_state(feedback_state),
86 nack_size(nack_size),
87 nack_list(nack_list),
88 repeat(repeat),
89 picture_id(picture_id),
90 buffer(buffer),
91 buffer_size(buffer_size),
92 ntp_sec(0),
93 ntp_frac(0),
Erik Språng242e22b2015-05-11 10:17:43 +020094 position(0) {}
95
96 uint8_t* AllocateData(uint32_t bytes) {
henrikg91d6ede2015-09-17 00:24:34 -070097 RTC_DCHECK_LE(position + bytes, buffer_size);
Erik Språng242e22b2015-05-11 10:17:43 +020098 uint8_t* ptr = &buffer[position];
99 position += bytes;
100 return ptr;
101 }
102
103 const FeedbackState& feedback_state;
104 int32_t nack_size;
105 const uint16_t* nack_list;
106 bool repeat;
107 uint64_t picture_id;
108 uint8_t* buffer;
109 uint32_t buffer_size;
110 uint32_t ntp_sec;
111 uint32_t ntp_frac;
Erik Språng242e22b2015-05-11 10:17:43 +0200112 uint32_t position;
113};
114
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200115// TODO(sprang): Once all builders use RtcpPacket, call SendToNetwork() here.
116class RTCPSender::PacketBuiltCallback
117 : public rtcp::RtcpPacket::PacketReadyCallback {
118 public:
119 PacketBuiltCallback(RtcpContext* context) : context_(context) {}
120 virtual ~PacketBuiltCallback() {}
121 void OnPacketReady(uint8_t* data, size_t length) override {
122 context_->position += length;
123 }
Erik Språng72aa9a62015-07-31 16:16:02 +0200124 bool BuildPacket(const rtcp::RtcpPacket& packet) {
125 return packet.BuildExternalBuffer(
126 &context_->buffer[context_->position],
127 context_->buffer_size - context_->position, this);
128 }
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200129
130 private:
131 RtcpContext* const context_;
132};
133
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000134RTCPSender::RTCPSender(
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000135 bool audio,
136 Clock* clock,
137 ReceiveStatistics* receive_statistics,
sprang86fd9ed2015-09-29 04:45:43 -0700138 RtcpPacketTypeCounterObserver* packet_type_counter_observer,
139 Transport* outgoing_transport)
Peter Boströmac547a62015-09-17 23:03:57 +0200140 : audio_(audio),
Erik Språng242e22b2015-05-11 10:17:43 +0200141 clock_(clock),
pbosda903ea2015-10-02 02:36:56 -0700142 method_(RtcpMode::kOff),
sprang86fd9ed2015-09-29 04:45:43 -0700143 transport_(outgoing_transport),
niklase@google.com470e71d2011-07-07 08:21:25 +0000144
Erik Språng242e22b2015-05-11 10:17:43 +0200145 critical_section_rtcp_sender_(
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000146 CriticalSectionWrapper::CreateCriticalSection()),
Erik Språng242e22b2015-05-11 10:17:43 +0200147 using_nack_(false),
148 sending_(false),
149 remb_enabled_(false),
Erik Språng242e22b2015-05-11 10:17:43 +0200150 next_time_to_send_rtcp_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000151 start_timestamp_(0),
152 last_rtp_timestamp_(0),
153 last_frame_capture_time_ms_(-1),
Erik Språng242e22b2015-05-11 10:17:43 +0200154 ssrc_(0),
155 remote_ssrc_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000156 receive_statistics_(receive_statistics),
niklase@google.com470e71d2011-07-07 08:21:25 +0000157
Erik Språng242e22b2015-05-11 10:17:43 +0200158 sequence_number_fir_(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000159
Erik Språng242e22b2015-05-11 10:17:43 +0200160 remb_bitrate_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000161
Erik Språng242e22b2015-05-11 10:17:43 +0200162 tmmbr_help_(),
163 tmmbr_send_(0),
164 packet_oh_send_(0),
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000165
Erik Språng242e22b2015-05-11 10:17:43 +0200166 app_sub_type_(0),
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200167 app_name_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200168 app_data_(nullptr),
169 app_length_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000170
Erik Språng242e22b2015-05-11 10:17:43 +0200171 xr_send_receiver_reference_time_enabled_(false),
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000172 packet_type_counter_observer_(packet_type_counter_observer) {
Erik Språng242e22b2015-05-11 10:17:43 +0200173 memset(last_send_report_, 0, sizeof(last_send_report_));
174 memset(last_rtcp_time_, 0, sizeof(last_rtcp_time_));
sprang86fd9ed2015-09-29 04:45:43 -0700175 RTC_DCHECK(transport_ != nullptr);
Erik Språng242e22b2015-05-11 10:17:43 +0200176
177 builders_[kRtcpSr] = &RTCPSender::BuildSR;
178 builders_[kRtcpRr] = &RTCPSender::BuildRR;
Erik Språng0ea42d32015-06-25 14:46:16 +0200179 builders_[kRtcpSdes] = &RTCPSender::BuildSDES;
Erik Språng242e22b2015-05-11 10:17:43 +0200180 builders_[kRtcpPli] = &RTCPSender::BuildPLI;
181 builders_[kRtcpFir] = &RTCPSender::BuildFIR;
182 builders_[kRtcpSli] = &RTCPSender::BuildSLI;
183 builders_[kRtcpRpsi] = &RTCPSender::BuildRPSI;
184 builders_[kRtcpRemb] = &RTCPSender::BuildREMB;
185 builders_[kRtcpBye] = &RTCPSender::BuildBYE;
186 builders_[kRtcpApp] = &RTCPSender::BuildAPP;
187 builders_[kRtcpTmmbr] = &RTCPSender::BuildTMMBR;
188 builders_[kRtcpTmmbn] = &RTCPSender::BuildTMMBN;
189 builders_[kRtcpNack] = &RTCPSender::BuildNACK;
190 builders_[kRtcpXrVoipMetric] = &RTCPSender::BuildVoIPMetric;
191 builders_[kRtcpXrReceiverReferenceTime] =
192 &RTCPSender::BuildReceiverReferenceTime;
193 builders_[kRtcpXrDlrrReportBlock] = &RTCPSender::BuildDlrr;
niklase@google.com470e71d2011-07-07 08:21:25 +0000194}
195
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000196RTCPSender::~RTCPSender() {
niklase@google.com470e71d2011-07-07 08:21:25 +0000197}
198
pbosda903ea2015-10-02 02:36:56 -0700199RtcpMode RTCPSender::Status() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200200 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
201 return method_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000202}
203
pbosda903ea2015-10-02 02:36:56 -0700204void RTCPSender::SetRTCPStatus(RtcpMode method) {
Erik Språng242e22b2015-05-11 10:17:43 +0200205 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
206 method_ = method;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000207
pbosda903ea2015-10-02 02:36:56 -0700208 if (method == RtcpMode::kOff)
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000209 return;
Erik Språng242e22b2015-05-11 10:17:43 +0200210 next_time_to_send_rtcp_ =
211 clock_->TimeInMilliseconds() +
212 (audio_ ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000213}
214
Erik Språng61be2a42015-04-27 13:32:52 +0200215bool RTCPSender::Sending() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200216 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
217 return sending_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000218}
219
Erik Språng61be2a42015-04-27 13:32:52 +0200220int32_t RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
221 bool sending) {
222 bool sendRTCPBye = false;
223 {
Erik Språng242e22b2015-05-11 10:17:43 +0200224 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000225
pbosda903ea2015-10-02 02:36:56 -0700226 if (method_ != RtcpMode::kOff) {
Erik Språng242e22b2015-05-11 10:17:43 +0200227 if (sending == false && sending_ == true) {
Erik Språng61be2a42015-04-27 13:32:52 +0200228 // Trigger RTCP bye
229 sendRTCPBye = true;
230 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000231 }
Erik Språng242e22b2015-05-11 10:17:43 +0200232 sending_ = sending;
Erik Språng61be2a42015-04-27 13:32:52 +0200233 }
234 if (sendRTCPBye)
235 return SendRTCP(feedback_state, kRtcpBye);
236 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000237}
238
Erik Språng61be2a42015-04-27 13:32:52 +0200239bool RTCPSender::REMB() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200240 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
241 return remb_enabled_;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000242}
243
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000244void RTCPSender::SetREMBStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200245 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
246 remb_enabled_ = enable;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000247}
248
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000249void RTCPSender::SetREMBData(uint32_t bitrate,
250 const std::vector<uint32_t>& ssrcs) {
Erik Språng242e22b2015-05-11 10:17:43 +0200251 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
252 remb_bitrate_ = bitrate;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000253 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000254
Erik Språng242e22b2015-05-11 10:17:43 +0200255 if (remb_enabled_)
256 SetFlag(kRtcpRemb, false);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000257 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
258 // throttled by the caller.
Erik Språng242e22b2015-05-11 10:17:43 +0200259 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000260}
261
Erik Språng61be2a42015-04-27 13:32:52 +0200262bool RTCPSender::TMMBR() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200263 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
264 return IsFlagPresent(RTCPPacketType::kRtcpTmmbr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000265}
266
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000267void RTCPSender::SetTMMBRStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200268 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
269 if (enable) {
270 SetFlag(RTCPPacketType::kRtcpTmmbr, false);
271 } else {
272 ConsumeFlag(RTCPPacketType::kRtcpTmmbr, true);
273 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000274}
275
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000276void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
Erik Språng242e22b2015-05-11 10:17:43 +0200277 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000278 start_timestamp_ = start_timestamp;
279}
280
281void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
282 int64_t capture_time_ms) {
Erik Språng242e22b2015-05-11 10:17:43 +0200283 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000284 last_rtp_timestamp_ = rtp_timestamp;
285 if (capture_time_ms < 0) {
286 // We don't currently get a capture time from VoiceEngine.
Erik Språng242e22b2015-05-11 10:17:43 +0200287 last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000288 } else {
289 last_frame_capture_time_ms_ = capture_time_ms;
290 }
291}
292
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000293void RTCPSender::SetSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200294 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000295
Erik Språng242e22b2015-05-11 10:17:43 +0200296 if (ssrc_ != 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200297 // not first SetSSRC, probably due to a collision
298 // schedule a new RTCP report
299 // make sure that we send a RTP packet
Erik Språng242e22b2015-05-11 10:17:43 +0200300 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
Erik Språng61be2a42015-04-27 13:32:52 +0200301 }
Erik Språng242e22b2015-05-11 10:17:43 +0200302 ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000303}
304
Erik Språng61be2a42015-04-27 13:32:52 +0200305void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200306 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
307 remote_ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000308}
309
Peter Boström9ba52f82015-06-01 14:12:28 +0200310int32_t RTCPSender::SetCNAME(const char* c_name) {
311 if (!c_name)
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000312 return -1;
313
henrikg91d6ede2015-09-17 00:24:34 -0700314 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
Erik Språng242e22b2015-05-11 10:17:43 +0200315 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200316 cname_ = c_name;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000317 return 0;
318}
319
Erik Språng0ea42d32015-06-25 14:46:16 +0200320int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC, const char* c_name) {
321 assert(c_name);
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 if (csrc_cnames_.size() >= kRtpCsrcSize)
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000325 return -1;
Erik Språng0ea42d32015-06-25 14:46:16 +0200326
327 csrc_cnames_[SSRC] = c_name;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000328 return 0;
329}
330
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000331int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
Erik Språng242e22b2015-05-11 10:17:43 +0200332 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200333 auto it = csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000334
Erik Språng242e22b2015-05-11 10:17:43 +0200335 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000336 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200337
Erik Språng242e22b2015-05-11 10:17:43 +0200338 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000339 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000340}
341
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000342bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
niklase@google.com470e71d2011-07-07 08:21:25 +0000343/*
344 For audio we use a fix 5 sec interval
345
346 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000347 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
348 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000349
350
351From RFC 3550
352
353 MAX RTCP BW is 5% if the session BW
354 A send report is approximately 65 bytes inc CNAME
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000355 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000356
357 The RECOMMENDED value for the reduced minimum in seconds is 360
358 divided by the session bandwidth in kilobits/second. This minimum
359 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
360
361 If the participant has not yet sent an RTCP packet (the variable
362 initial is true), the constant Tmin is set to 2.5 seconds, else it
363 is set to 5 seconds.
364
365 The interval between RTCP packets is varied randomly over the
366 range [0.5,1.5] times the calculated interval to avoid unintended
367 synchronization of all participants
368
369 if we send
370 If the participant is a sender (we_sent true), the constant C is
371 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
372 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
373 number of senders.
374
375 if we receive only
376 If we_sent is not true, the constant C is set
377 to the average RTCP packet size divided by 75% of the RTCP
378 bandwidth. The constant n is set to the number of receivers
379 (members - senders). If the number of senders is greater than
380 25%, senders and receivers are treated together.
381
382 reconsideration NOT required for peer-to-peer
383 "timer reconsideration" is
384 employed. This algorithm implements a simple back-off mechanism
385 which causes users to hold back RTCP packet transmission if the
386 group sizes are increasing.
387
388 n = number of members
389 C = avg_size/(rtcpBW/4)
390
391 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
392
393 4. The calculated interval T is set to a number uniformly distributed
394 between 0.5 and 1.5 times the deterministic calculated interval.
395
396 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
397 for the fact that the timer reconsideration algorithm converges to
398 a value of the RTCP bandwidth below the intended average
399*/
400
Erik Språng242e22b2015-05-11 10:17:43 +0200401 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000402
Erik Språng242e22b2015-05-11 10:17:43 +0200403 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
xians@webrtc.org8738d272011-11-25 13:43:53 +0000404
pbosda903ea2015-10-02 02:36:56 -0700405 if (method_ == RtcpMode::kOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000406 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000407
Erik Språng242e22b2015-05-11 10:17:43 +0200408 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200409 // for video key-frames we want to send the RTCP before the large key-frame
410 // if we have a 100 ms margin
411 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
412 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000413
Erik Språng242e22b2015-05-11 10:17:43 +0200414 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200415 return true;
416 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200417 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200418 // wrap
419 return true;
420 }
421 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000422}
423
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000424int64_t RTCPSender::SendTimeOfSendReport(uint32_t sendReport) {
Erik Språng242e22b2015-05-11 10:17:43 +0200425 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000426
Erik Språng61be2a42015-04-27 13:32:52 +0200427 // This is only saved when we are the sender
Erik Språng242e22b2015-05-11 10:17:43 +0200428 if ((last_send_report_[0] == 0) || (sendReport == 0)) {
Erik Språng61be2a42015-04-27 13:32:52 +0200429 return 0; // will be ignored
430 } else {
431 for (int i = 0; i < RTCP_NUMBER_OF_SR; ++i) {
Erik Språng242e22b2015-05-11 10:17:43 +0200432 if (last_send_report_[i] == sendReport)
433 return last_rtcp_time_[i];
niklase@google.com470e71d2011-07-07 08:21:25 +0000434 }
Erik Språng61be2a42015-04-27 13:32:52 +0200435 }
436 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000437}
438
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000439bool RTCPSender::SendTimeOfXrRrReport(uint32_t mid_ntp,
440 int64_t* time_ms) const {
Erik Språng242e22b2015-05-11 10:17:43 +0200441 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000442
443 if (last_xr_rr_.empty()) {
444 return false;
445 }
446 std::map<uint32_t, int64_t>::const_iterator it = last_xr_rr_.find(mid_ntp);
447 if (it == last_xr_rr_.end()) {
448 return false;
449 }
450 *time_ms = it->second;
451 return true;
452}
453
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200454int32_t RTCPSender::AddReportBlock(const RTCPReportBlock& report_block) {
455 if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000456 LOG(LS_WARNING) << "Too many report blocks.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000457 return -1;
458 }
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200459 rtcp::ReportBlock* block = &report_blocks_[report_block.remoteSSRC];
460 block->To(report_block.remoteSSRC);
461 block->WithFractionLost(report_block.fractionLost);
danilchapdf948f02015-11-13 03:03:13 -0800462 if (!block->WithCumulativeLost(report_block.cumulativeLost)) {
463 LOG(LS_WARNING) << "Cumulative lost is oversized.";
464 return -1;
465 }
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200466 block->WithExtHighestSeqNum(report_block.extendedHighSeqNum);
467 block->WithJitter(report_block.jitter);
468 block->WithLastSr(report_block.lastSR);
469 block->WithDelayLastSr(report_block.delaySinceLastSR);
470
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000471 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000472}
473
Erik Språng242e22b2015-05-11 10:17:43 +0200474RTCPSender::BuildResult RTCPSender::BuildSR(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200475 for (int i = (RTCP_NUMBER_OF_SR - 2); i >= 0; i--) {
476 // shift old
Erik Språng242e22b2015-05-11 10:17:43 +0200477 last_send_report_[i + 1] = last_send_report_[i];
478 last_rtcp_time_[i + 1] = last_rtcp_time_[i];
Erik Språng61be2a42015-04-27 13:32:52 +0200479 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000480
Erik Språng242e22b2015-05-11 10:17:43 +0200481 last_rtcp_time_[0] = Clock::NtpToMs(ctx->ntp_sec, ctx->ntp_frac);
482 last_send_report_[0] = (ctx->ntp_sec << 16) + (ctx->ntp_frac >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000483
Erik Språng61be2a42015-04-27 13:32:52 +0200484 // The timestamp of this RTCP packet should be estimated as the timestamp of
485 // the frame being captured at this moment. We are calculating that
486 // timestamp as the last frame's timestamp + the time since the last frame
487 // was captured.
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200488 uint32_t rtp_timestamp =
489 start_timestamp_ + last_rtp_timestamp_ +
490 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) *
491 (ctx->feedback_state.frequency_hz / 1000);
niklase@google.com470e71d2011-07-07 08:21:25 +0000492
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200493 rtcp::SenderReport report;
494 report.From(ssrc_);
495 report.WithNtpSec(ctx->ntp_sec);
496 report.WithNtpFrac(ctx->ntp_frac);
497 report.WithRtpTimestamp(rtp_timestamp);
498 report.WithPacketCount(ctx->feedback_state.packets_sent);
499 report.WithOctetCount(ctx->feedback_state.media_bytes_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000500
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200501 for (auto it : report_blocks_)
502 report.WithReportBlock(it.second);
niklase@google.com470e71d2011-07-07 08:21:25 +0000503
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200504 PacketBuiltCallback callback(ctx);
Erik Språng72aa9a62015-07-31 16:16:02 +0200505 if (!callback.BuildPacket(report))
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200506 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000507
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200508 report_blocks_.clear();
Erik Språng242e22b2015-05-11 10:17:43 +0200509 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000510}
511
Erik Språng0ea42d32015-06-25 14:46:16 +0200512RTCPSender::BuildResult RTCPSender::BuildSDES(RtcpContext* ctx) {
513 size_t length_cname = cname_.length();
henrikg91d6ede2015-09-17 00:24:34 -0700514 RTC_CHECK_LT(length_cname, static_cast<size_t>(RTCP_CNAME_SIZE));
niklase@google.com470e71d2011-07-07 08:21:25 +0000515
Erik Språng0ea42d32015-06-25 14:46:16 +0200516 rtcp::Sdes sdes;
517 sdes.WithCName(ssrc_, cname_);
518
519 for (const auto it : csrc_cnames_)
520 sdes.WithCName(it.first, it.second);
521
522 PacketBuiltCallback callback(ctx);
Erik Språng72aa9a62015-07-31 16:16:02 +0200523 if (!callback.BuildPacket(sdes))
Erik Språng242e22b2015-05-11 10:17:43 +0200524 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000525
Erik Språng242e22b2015-05-11 10:17:43 +0200526 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000527}
528
Erik Språng242e22b2015-05-11 10:17:43 +0200529RTCPSender::BuildResult RTCPSender::BuildRR(RtcpContext* ctx) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200530 rtcp::ReceiverReport report;
531 report.From(ssrc_);
532 for (auto it : report_blocks_)
533 report.WithReportBlock(it.second);
534
535 PacketBuiltCallback callback(ctx);
Erik Språng72aa9a62015-07-31 16:16:02 +0200536 if (!callback.BuildPacket(report))
Erik Språng242e22b2015-05-11 10:17:43 +0200537 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200538
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200539 report_blocks_.clear();
Erik Språng242e22b2015-05-11 10:17:43 +0200540
541 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000542}
543
Erik Språng242e22b2015-05-11 10:17:43 +0200544RTCPSender::BuildResult RTCPSender::BuildPLI(RtcpContext* ctx) {
Erik Språng72aa9a62015-07-31 16:16:02 +0200545 rtcp::Pli pli;
546 pli.From(ssrc_);
547 pli.To(remote_ssrc_);
548
549 PacketBuiltCallback callback(ctx);
550 if (!callback.BuildPacket(pli))
Erik Språng242e22b2015-05-11 10:17:43 +0200551 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200552
Erik Språng242e22b2015-05-11 10:17:43 +0200553 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
554 "RTCPSender::PLI");
555 ++packet_type_counter_.pli_packets;
556 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
557 ssrc_, packet_type_counter_.pli_packets);
558
559 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +0200560}
561
Erik Språng242e22b2015-05-11 10:17:43 +0200562RTCPSender::BuildResult RTCPSender::BuildFIR(RtcpContext* ctx) {
Erik Språng242e22b2015-05-11 10:17:43 +0200563 if (!ctx->repeat)
sprang62dae192015-08-05 02:35:35 -0700564 ++sequence_number_fir_; // Do not increase if repetition.
niklase@google.com470e71d2011-07-07 08:21:25 +0000565
sprang62dae192015-08-05 02:35:35 -0700566 rtcp::Fir fir;
567 fir.From(ssrc_);
568 fir.To(remote_ssrc_);
569 fir.WithCommandSeqNum(sequence_number_fir_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000570
sprang62dae192015-08-05 02:35:35 -0700571 PacketBuiltCallback callback(ctx);
572 if (!callback.BuildPacket(fir))
573 return BuildResult::kTruncated;
Erik Språng242e22b2015-05-11 10:17:43 +0200574
575 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
576 "RTCPSender::FIR");
577 ++packet_type_counter_.fir_packets;
578 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
579 ssrc_, packet_type_counter_.fir_packets);
580
581 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000582}
583
584/*
585 0 1 2 3
586 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
587 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
588 | First | Number | PictureID |
589 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
590*/
Erik Språng242e22b2015-05-11 10:17:43 +0200591RTCPSender::BuildResult RTCPSender::BuildSLI(RtcpContext* ctx) {
sprang0365a272015-08-11 01:02:37 -0700592 rtcp::Sli sli;
593 sli.From(ssrc_);
594 sli.To(remote_ssrc_);
595 // Crop picture id to 6 least significant bits.
596 sli.WithPictureId(ctx->picture_id & 0x3F);
597 sli.WithFirstMb(0);
598 sli.WithNumberOfMb(0x1FFF); // 13 bits, only ones for now.
599
600 PacketBuiltCallback callback(ctx);
601 if (!callback.BuildPacket(sli))
Erik Språng242e22b2015-05-11 10:17:43 +0200602 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000603
Erik Språng242e22b2015-05-11 10:17:43 +0200604 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000605}
606
607/*
608 0 1 2 3
609 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
610 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
611 | PB |0| Payload Type| Native RPSI bit string |
612 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
613 | defined per codec ... | Padding (0) |
614 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
615*/
616/*
617* Note: not generic made for VP8
618*/
Erik Språng242e22b2015-05-11 10:17:43 +0200619RTCPSender::BuildResult RTCPSender::BuildRPSI(RtcpContext* ctx) {
620 if (ctx->feedback_state.send_payload_type == 0xFF)
621 return BuildResult::kError;
622
sprangcf7f54d2015-08-13 04:37:42 -0700623 rtcp::Rpsi rpsi;
624 rpsi.From(ssrc_);
625 rpsi.To(remote_ssrc_);
626 rpsi.WithPayloadType(ctx->feedback_state.send_payload_type);
627 rpsi.WithPictureId(ctx->picture_id);
628
629 PacketBuiltCallback callback(ctx);
630 if (!callback.BuildPacket(rpsi))
Erik Språng242e22b2015-05-11 10:17:43 +0200631 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000632
Erik Språng242e22b2015-05-11 10:17:43 +0200633 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000634}
635
Erik Språng242e22b2015-05-11 10:17:43 +0200636RTCPSender::BuildResult RTCPSender::BuildREMB(RtcpContext* ctx) {
sprangdd4edc52015-08-21 04:21:51 -0700637 rtcp::Remb remb;
638 remb.From(ssrc_);
639 for (uint32_t ssrc : remb_ssrcs_)
640 remb.AppliesTo(ssrc);
641 remb.WithBitrateBps(remb_bitrate_);
642
643 PacketBuiltCallback callback(ctx);
644 if (!callback.BuildPacket(remb))
Erik Språng242e22b2015-05-11 10:17:43 +0200645 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200646
Erik Språng242e22b2015-05-11 10:17:43 +0200647 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
648 "RTCPSender::REMB");
649
650 return BuildResult::kSuccess;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000651}
652
Erik Språng61be2a42015-04-27 13:32:52 +0200653void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
Erik Språng242e22b2015-05-11 10:17:43 +0200654 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
655 tmmbr_send_ = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000656}
657
Erik Språng242e22b2015-05-11 10:17:43 +0200658RTCPSender::BuildResult RTCPSender::BuildTMMBR(RtcpContext* ctx) {
659 if (ctx->feedback_state.module == NULL)
660 return BuildResult::kError;
Erik Språng61be2a42015-04-27 13:32:52 +0200661 // Before sending the TMMBR check the received TMMBN, only an owner is
662 // allowed to raise the bitrate:
663 // * If the sender is an owner of the TMMBN -> send TMMBR
664 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000665
Erik Språng61be2a42015-04-27 13:32:52 +0200666 // get current bounding set from RTCP receiver
667 bool tmmbrOwner = false;
668 // store in candidateSet, allocates one extra slot
Erik Språng242e22b2015-05-11 10:17:43 +0200669 TMMBRSet* candidateSet = tmmbr_help_.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000670
Erik Språng242e22b2015-05-11 10:17:43 +0200671 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
672 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
Erik Språng61be2a42015-04-27 13:32:52 +0200673 // since RTCPreceiver is not doing the reverse we should be fine
674 int32_t lengthOfBoundingSet =
Erik Språng242e22b2015-05-11 10:17:43 +0200675 ctx->feedback_state.module->BoundingSet(tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +0000676
Erik Språng61be2a42015-04-27 13:32:52 +0200677 if (lengthOfBoundingSet > 0) {
678 for (int32_t i = 0; i < lengthOfBoundingSet; i++) {
Erik Språng242e22b2015-05-11 10:17:43 +0200679 if (candidateSet->Tmmbr(i) == tmmbr_send_ &&
680 candidateSet->PacketOH(i) == packet_oh_send_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200681 // do not send the same tuple
Erik Språng242e22b2015-05-11 10:17:43 +0200682 return BuildResult::kAborted;
Erik Språng61be2a42015-04-27 13:32:52 +0200683 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000684 }
Erik Språng61be2a42015-04-27 13:32:52 +0200685 if (!tmmbrOwner) {
686 // use received bounding set as candidate set
687 // add current tuple
Erik Språng242e22b2015-05-11 10:17:43 +0200688 candidateSet->SetEntry(lengthOfBoundingSet, tmmbr_send_, packet_oh_send_,
689 ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200690 int numCandidates = lengthOfBoundingSet + 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000691
Erik Språng61be2a42015-04-27 13:32:52 +0200692 // find bounding set
693 TMMBRSet* boundingSet = NULL;
Erik Språng242e22b2015-05-11 10:17:43 +0200694 int numBoundingSet = tmmbr_help_.FindTMMBRBoundingSet(boundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200695 if (numBoundingSet > 0 || numBoundingSet <= numCandidates)
Erik Språng242e22b2015-05-11 10:17:43 +0200696 tmmbrOwner = tmmbr_help_.IsOwner(ssrc_, numBoundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200697 if (!tmmbrOwner) {
698 // did not enter bounding set, no meaning to send this request
Erik Språng242e22b2015-05-11 10:17:43 +0200699 return BuildResult::kAborted;
Erik Språng61be2a42015-04-27 13:32:52 +0200700 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000701 }
Erik Språng61be2a42015-04-27 13:32:52 +0200702 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000703
Erik Språng242e22b2015-05-11 10:17:43 +0200704 if (tmmbr_send_) {
sprang81a3e602015-08-21 05:30:11 -0700705 rtcp::Tmmbr tmmbr;
706 tmmbr.From(ssrc_);
707 tmmbr.To(remote_ssrc_);
708 tmmbr.WithBitrateKbps(tmmbr_send_);
709 tmmbr.WithOverhead(packet_oh_send_);
710
711 PacketBuiltCallback callback(ctx);
712 if (!callback.BuildPacket(tmmbr))
Erik Språng242e22b2015-05-11 10:17:43 +0200713 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200714 }
Erik Språng242e22b2015-05-11 10:17:43 +0200715 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +0200716}
717
Erik Språng242e22b2015-05-11 10:17:43 +0200718RTCPSender::BuildResult RTCPSender::BuildTMMBN(RtcpContext* ctx) {
719 TMMBRSet* boundingSet = tmmbr_help_.BoundingSetToSend();
Erik Språng61be2a42015-04-27 13:32:52 +0200720 if (boundingSet == NULL)
Erik Språng242e22b2015-05-11 10:17:43 +0200721 return BuildResult::kError;
Erik Språng61be2a42015-04-27 13:32:52 +0200722
sprangd83df502015-08-27 01:05:08 -0700723 rtcp::Tmmbn tmmbn;
724 tmmbn.From(ssrc_);
725 for (uint32_t i = 0; i < boundingSet->lengthOfSet(); i++) {
726 if (boundingSet->Tmmbr(i) > 0) {
727 tmmbn.WithTmmbr(boundingSet->Ssrc(i), boundingSet->Tmmbr(i),
728 boundingSet->PacketOH(i));
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000729 }
Erik Språng61be2a42015-04-27 13:32:52 +0200730 }
sprangd83df502015-08-27 01:05:08 -0700731
732 PacketBuiltCallback callback(ctx);
733 if (!callback.BuildPacket(tmmbn))
734 return BuildResult::kTruncated;
Erik Språng242e22b2015-05-11 10:17:43 +0200735
736 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000737}
738
Erik Språng242e22b2015-05-11 10:17:43 +0200739RTCPSender::BuildResult RTCPSender::BuildAPP(RtcpContext* ctx) {
Erik Språng521875a2015-09-01 10:11:16 +0200740 rtcp::App app;
741 app.From(ssrc_);
742 app.WithSubType(app_sub_type_);
743 app.WithName(app_name_);
744 app.WithData(app_data_.get(), app_length_);
745
746 PacketBuiltCallback callback(ctx);
747 if (!callback.BuildPacket(app))
Erik Språng242e22b2015-05-11 10:17:43 +0200748 return BuildResult::kTruncated;
Erik Språng242e22b2015-05-11 10:17:43 +0200749
750 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +0200751}
752
Erik Språng242e22b2015-05-11 10:17:43 +0200753RTCPSender::BuildResult RTCPSender::BuildNACK(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200754 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200755 if (ctx->position + 16 >= IP_PACKET_SIZE) {
Erik Språng61be2a42015-04-27 13:32:52 +0200756 LOG(LS_WARNING) << "Failed to build NACK.";
Erik Språng242e22b2015-05-11 10:17:43 +0200757 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200758 }
759
Erik Språng242e22b2015-05-11 10:17:43 +0200760 // int size, uint16_t* nack_list
Erik Språng61be2a42015-04-27 13:32:52 +0200761 // add nack list
762 uint8_t FMT = 1;
Erik Språng242e22b2015-05-11 10:17:43 +0200763 *ctx->AllocateData(1) = 0x80 + FMT;
764 *ctx->AllocateData(1) = 205;
Erik Språng61be2a42015-04-27 13:32:52 +0200765
Erik Språng242e22b2015-05-11 10:17:43 +0200766 *ctx->AllocateData(1) = 0;
767 int nack_size_pos_ = ctx->position;
768 *ctx->AllocateData(1) = 3; // setting it to one kNACK signal as default
Erik Språng61be2a42015-04-27 13:32:52 +0200769
770 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200771 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200772
773 // Add the remote SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200774 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200775
776 // Build NACK bitmasks and write them to the RTCP message.
777 // The nack list should be sorted and not contain duplicates if one
778 // wants to build the smallest rtcp nack packet.
779 int numOfNackFields = 0;
780 int maxNackFields =
Erik Språng242e22b2015-05-11 10:17:43 +0200781 std::min<int>(kRtcpMaxNackFields, (IP_PACKET_SIZE - ctx->position) / 4);
Erik Språng61be2a42015-04-27 13:32:52 +0200782 int i = 0;
Erik Språng242e22b2015-05-11 10:17:43 +0200783 while (i < ctx->nack_size && numOfNackFields < maxNackFields) {
784 uint16_t nack = ctx->nack_list[i++];
Erik Språng61be2a42015-04-27 13:32:52 +0200785 uint16_t bitmask = 0;
Erik Språng242e22b2015-05-11 10:17:43 +0200786 while (i < ctx->nack_size) {
787 int shift = static_cast<uint16_t>(ctx->nack_list[i] - nack) - 1;
Erik Språng61be2a42015-04-27 13:32:52 +0200788 if (shift >= 0 && shift <= 15) {
789 bitmask |= (1 << shift);
790 ++i;
791 } else {
792 break;
793 }
794 }
795 // Write the sequence number and the bitmask to the packet.
Erik Språng242e22b2015-05-11 10:17:43 +0200796 assert(ctx->position + 4 < IP_PACKET_SIZE);
797 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2), nack);
798 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2), bitmask);
Erik Språng61be2a42015-04-27 13:32:52 +0200799 numOfNackFields++;
800 }
Erik Språng242e22b2015-05-11 10:17:43 +0200801 ctx->buffer[nack_size_pos_] = static_cast<uint8_t>(2 + numOfNackFields);
Erik Språng61be2a42015-04-27 13:32:52 +0200802
Erik Språng242e22b2015-05-11 10:17:43 +0200803 if (i != ctx->nack_size)
Erik Språng61be2a42015-04-27 13:32:52 +0200804 LOG(LS_WARNING) << "Nack list too large for one packet.";
805
806 // Report stats.
807 NACKStringBuilder stringBuilder;
808 for (int idx = 0; idx < i; ++idx) {
Erik Språng242e22b2015-05-11 10:17:43 +0200809 stringBuilder.PushNACK(ctx->nack_list[idx]);
810 nack_stats_.ReportRequest(ctx->nack_list[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +0200811 }
Erik Språng61be2a42015-04-27 13:32:52 +0200812 packet_type_counter_.nack_requests = nack_stats_.requests();
813 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +0200814
815 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
816 "RTCPSender::NACK", "nacks",
817 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
818 ++packet_type_counter_.nack_packets;
819 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
820 ssrc_, packet_type_counter_.nack_packets);
821
822 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +0200823}
824
Erik Språng242e22b2015-05-11 10:17:43 +0200825RTCPSender::BuildResult RTCPSender::BuildBYE(RtcpContext* ctx) {
sprangd8ee4f92015-08-24 03:25:19 -0700826 rtcp::Bye bye;
827 bye.From(ssrc_);
828 for (uint32_t csrc : csrcs_)
829 bye.WithCsrc(csrc);
830
831 PacketBuiltCallback callback(ctx);
832 if (!callback.BuildPacket(bye))
Erik Språng242e22b2015-05-11 10:17:43 +0200833 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000834
Erik Språng242e22b2015-05-11 10:17:43 +0200835 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000836}
837
Erik Språng242e22b2015-05-11 10:17:43 +0200838RTCPSender::BuildResult RTCPSender::BuildReceiverReferenceTime(
839 RtcpContext* ctx) {
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000840
Erik Språng61be2a42015-04-27 13:32:52 +0200841 if (last_xr_rr_.size() >= RTCP_NUMBER_OF_SR)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000842 last_xr_rr_.erase(last_xr_rr_.begin());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000843 last_xr_rr_.insert(std::pair<uint32_t, int64_t>(
Erik Språng242e22b2015-05-11 10:17:43 +0200844 RTCPUtility::MidNtp(ctx->ntp_sec, ctx->ntp_frac),
845 Clock::NtpToMs(ctx->ntp_sec, ctx->ntp_frac)));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000846
Erik Språngca28fdc2015-08-31 14:00:50 +0200847 rtcp::Xr xr;
848 xr.From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000849
Erik Språngca28fdc2015-08-31 14:00:50 +0200850 rtcp::Rrtr rrtr;
851 rrtr.WithNtpSec(ctx->ntp_sec);
852 rrtr.WithNtpFrac(ctx->ntp_frac);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000853
Erik Språngca28fdc2015-08-31 14:00:50 +0200854 xr.WithRrtr(&rrtr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000855
Erik Språngca28fdc2015-08-31 14:00:50 +0200856 // TODO(sprang): Merge XR report sending to contain all of RRTR, DLRR, VOIP?
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000857
Erik Språngca28fdc2015-08-31 14:00:50 +0200858 PacketBuiltCallback callback(ctx);
859 if (!callback.BuildPacket(xr))
860 return BuildResult::kTruncated;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000861
Erik Språng242e22b2015-05-11 10:17:43 +0200862 return BuildResult::kSuccess;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000863}
864
Erik Språng242e22b2015-05-11 10:17:43 +0200865RTCPSender::BuildResult RTCPSender::BuildDlrr(RtcpContext* ctx) {
Erik Språngca28fdc2015-08-31 14:00:50 +0200866 rtcp::Xr xr;
867 xr.From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000868
Erik Språngca28fdc2015-08-31 14:00:50 +0200869 rtcp::Dlrr dlrr;
Erik Språng242e22b2015-05-11 10:17:43 +0200870 const RtcpReceiveTimeInfo& info = ctx->feedback_state.last_xr_rr;
Erik Språngca28fdc2015-08-31 14:00:50 +0200871 dlrr.WithDlrrItem(info.sourceSSRC, info.lastRR, info.delaySinceLastRR);
872
873 xr.WithDlrr(&dlrr);
874
875 PacketBuiltCallback callback(ctx);
876 if (!callback.BuildPacket(xr))
877 return BuildResult::kTruncated;
Erik Språng242e22b2015-05-11 10:17:43 +0200878
879 return BuildResult::kSuccess;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000880}
881
Erik Språng242e22b2015-05-11 10:17:43 +0200882// TODO(sprang): Add a unit test for this, or remove if the code isn't used.
883RTCPSender::BuildResult RTCPSender::BuildVoIPMetric(RtcpContext* ctx) {
Erik Språngca28fdc2015-08-31 14:00:50 +0200884 rtcp::Xr xr;
885 xr.From(ssrc_);
886
887 rtcp::VoipMetric voip;
888 voip.To(remote_ssrc_);
889 voip.LossRate(xr_voip_metric_.lossRate);
890 voip.DiscardRate(xr_voip_metric_.discardRate);
891 voip.BurstDensity(xr_voip_metric_.burstDensity);
892 voip.GapDensity(xr_voip_metric_.gapDensity);
893 voip.BurstDuration(xr_voip_metric_.burstDuration);
894 voip.GapDuration(xr_voip_metric_.gapDuration);
895 voip.RoundTripDelay(xr_voip_metric_.roundTripDelay);
896 voip.EndSystemDelay(xr_voip_metric_.endSystemDelay);
897 voip.SignalLevel(xr_voip_metric_.signalLevel);
898 voip.NoiseLevel(xr_voip_metric_.noiseLevel);
899 voip.Rerl(xr_voip_metric_.RERL);
900 voip.Gmin(xr_voip_metric_.Gmin);
901 voip.Rfactor(xr_voip_metric_.Rfactor);
902 voip.ExtRfactor(xr_voip_metric_.extRfactor);
903 voip.MosLq(xr_voip_metric_.MOSLQ);
904 voip.MosCq(xr_voip_metric_.MOSCQ);
905 voip.RxConfig(xr_voip_metric_.RXconfig);
906 voip.JbNominal(xr_voip_metric_.JBnominal);
907 voip.JbMax(xr_voip_metric_.JBmax);
908 voip.JbAbsMax(xr_voip_metric_.JBabsMax);
909
910 xr.WithVoipMetric(&voip);
911
912 PacketBuiltCallback callback(ctx);
913 if (!callback.BuildPacket(xr))
Erik Språng242e22b2015-05-11 10:17:43 +0200914 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000915
Erik Språng242e22b2015-05-11 10:17:43 +0200916 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000917}
918
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000919int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200920 RTCPPacketType packetType,
921 int32_t nack_size,
922 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000923 bool repeat,
924 uint64_t pictureID) {
Erik Språng242e22b2015-05-11 10:17:43 +0200925 return SendCompoundRTCP(
926 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
927 nack_size, nack_list, repeat, pictureID);
928}
929
930int32_t RTCPSender::SendCompoundRTCP(
931 const FeedbackState& feedback_state,
932 const std::set<RTCPPacketType>& packetTypes,
933 int32_t nack_size,
934 const uint16_t* nack_list,
935 bool repeat,
936 uint64_t pictureID) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000937 {
Erik Språng242e22b2015-05-11 10:17:43 +0200938 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
pbosda903ea2015-10-02 02:36:56 -0700939 if (method_ == RtcpMode::kOff) {
Erik Språng61be2a42015-04-27 13:32:52 +0200940 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
941 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +0000942 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000943 }
944 uint8_t rtcp_buffer[IP_PACKET_SIZE];
Erik Språng242e22b2015-05-11 10:17:43 +0200945 int rtcp_length =
946 PrepareRTCP(feedback_state, packetTypes, nack_size, nack_list, repeat,
947 pictureID, rtcp_buffer, IP_PACKET_SIZE);
Erik Språng61be2a42015-04-27 13:32:52 +0200948
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000949 // Sanity don't send empty packets.
Erik Språng242e22b2015-05-11 10:17:43 +0200950 if (rtcp_length <= 0)
951 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200952
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000953 return SendToNetwork(rtcp_buffer, static_cast<size_t>(rtcp_length));
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000954}
955
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000956int RTCPSender::PrepareRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200957 const std::set<RTCPPacketType>& packetTypes,
958 int32_t nack_size,
959 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000960 bool repeat,
961 uint64_t pictureID,
962 uint8_t* rtcp_buffer,
963 int buffer_size) {
Erik Språng242e22b2015-05-11 10:17:43 +0200964 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000965
Erik Språng242e22b2015-05-11 10:17:43 +0200966 RtcpContext context(feedback_state, nack_size, nack_list, repeat, pictureID,
967 rtcp_buffer, buffer_size);
968
969 // Add all flags as volatile. Non volatile entries will not be overwritten
970 // and all new volatile flags added will be consumed by the end of this call.
971 SetFlags(packetTypes, true);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000972
Erik Språng61be2a42015-04-27 13:32:52 +0200973 if (packet_type_counter_.first_packet_time_ms == -1)
Erik Språng242e22b2015-05-11 10:17:43 +0200974 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språng61be2a42015-04-27 13:32:52 +0200975
Erik Språng242e22b2015-05-11 10:17:43 +0200976 bool generate_report;
977 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
978 // Report type already explicitly set, don't automatically populate.
979 generate_report = true;
henrikg91d6ede2015-09-17 00:24:34 -0700980 RTC_DCHECK(ConsumeFlag(kRtcpReport) == false);
Erik Språng242e22b2015-05-11 10:17:43 +0200981 } else {
982 generate_report =
pbosda903ea2015-10-02 02:36:56 -0700983 (ConsumeFlag(kRtcpReport) && method_ == RtcpMode::kReducedSize) ||
984 method_ == RtcpMode::kCompound;
Erik Språng242e22b2015-05-11 10:17:43 +0200985 if (generate_report)
986 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000987 }
988
Erik Språng0ea42d32015-06-25 14:46:16 +0200989 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
Erik Språng242e22b2015-05-11 10:17:43 +0200990 SetFlag(kRtcpSdes, true);
991
992 // We need to send our NTP even if we haven't received any reports.
993 clock_->CurrentNtp(context.ntp_sec, context.ntp_frac);
994
995 if (generate_report) {
996 if (!sending_ && xr_send_receiver_reference_time_enabled_)
997 SetFlag(kRtcpXrReceiverReferenceTime, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200998 if (feedback_state.has_last_xr_rr)
Erik Språng242e22b2015-05-11 10:17:43 +0200999 SetFlag(kRtcpXrDlrrReportBlock, true);
1000
1001 // generate next time to send an RTCP report
Erik Språng61be2a42015-04-27 13:32:52 +02001002 // seeded from RTP constructor
1003 int32_t random = rand() % 1000;
1004 int32_t timeToNext = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001005
Erik Språng242e22b2015-05-11 10:17:43 +02001006 if (audio_) {
Erik Språng61be2a42015-04-27 13:32:52 +02001007 timeToNext = (RTCP_INTERVAL_AUDIO_MS / 2) +
1008 (RTCP_INTERVAL_AUDIO_MS * random / 1000);
1009 } else {
1010 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
Erik Språng242e22b2015-05-11 10:17:43 +02001011 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +02001012 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
1013 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
1014 if (send_bitrate_kbit != 0)
1015 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001016 }
Erik Språng61be2a42015-04-27 13:32:52 +02001017 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
1018 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
1019 timeToNext = (minIntervalMs / 2) + (minIntervalMs * random / 1000);
1020 }
Erik Språng242e22b2015-05-11 10:17:43 +02001021 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001022
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001023 StatisticianMap statisticians =
1024 receive_statistics_->GetActiveStatisticians();
1025 if (!statisticians.empty()) {
Erik Språng61be2a42015-04-27 13:32:52 +02001026 for (auto it = statisticians.begin(); it != statisticians.end(); ++it) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001027 RTCPReportBlock report_block;
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001028 if (PrepareReport(feedback_state, it->first, it->second,
1029 &report_block)) {
danilchapdf948f02015-11-13 03:03:13 -08001030 // TODO(danilchap) AddReportBlock may fail (for 2 different reasons).
1031 // Probably it shouldn't be ignored.
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001032 AddReportBlock(report_block);
Erik Språng61be2a42015-04-27 13:32:52 +02001033 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001034 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001035 }
1036 }
1037
Erik Språng242e22b2015-05-11 10:17:43 +02001038 auto it = report_flags_.begin();
1039 while (it != report_flags_.end()) {
1040 auto builder = builders_.find(it->type);
henrikg91d6ede2015-09-17 00:24:34 -07001041 RTC_DCHECK(builder != builders_.end());
Erik Språng242e22b2015-05-11 10:17:43 +02001042 if (it->is_volatile) {
1043 report_flags_.erase(it++);
1044 } else {
1045 ++it;
Erik Språng61be2a42015-04-27 13:32:52 +02001046 }
Erik Språng242e22b2015-05-11 10:17:43 +02001047
1048 uint32_t start_position = context.position;
Erik Språng0ea42d32015-06-25 14:46:16 +02001049 BuildResult result = (this->*(builder->second))(&context);
Erik Språng242e22b2015-05-11 10:17:43 +02001050 switch (result) {
1051 case BuildResult::kError:
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001052 return -1;
Erik Språng242e22b2015-05-11 10:17:43 +02001053 case BuildResult::kTruncated:
1054 return context.position;
1055 case BuildResult::kAborted:
1056 context.position = start_position;
1057 FALLTHROUGH();
1058 case BuildResult::kSuccess:
1059 continue;
Erik Språng61be2a42015-04-27 13:32:52 +02001060 default:
Erik Språng242e22b2015-05-11 10:17:43 +02001061 abort();
Erik Språng61be2a42015-04-27 13:32:52 +02001062 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001063 }
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001064
1065 if (packet_type_counter_observer_ != NULL) {
1066 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
Erik Språng242e22b2015-05-11 10:17:43 +02001067 remote_ssrc_, packet_type_counter_);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001068 }
1069
henrikg91d6ede2015-09-17 00:24:34 -07001070 RTC_DCHECK(AllVolatileFlagsConsumed());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001071
Erik Språng242e22b2015-05-11 10:17:43 +02001072 return context.position;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001073}
1074
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001075bool RTCPSender::PrepareReport(const FeedbackState& feedback_state,
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001076 uint32_t ssrc,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001077 StreamStatistician* statistician,
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001078 RTCPReportBlock* report_block) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001079 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +00001080 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001081 if (!statistician->GetStatistics(&stats, true))
1082 return false;
1083 report_block->fractionLost = stats.fraction_lost;
1084 report_block->cumulativeLost = stats.cumulative_lost;
1085 report_block->extendedHighSeqNum =
1086 stats.extended_max_sequence_number;
1087 report_block->jitter = stats.jitter;
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001088 report_block->remoteSSRC = ssrc;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001089
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001090 // TODO(sprang): Do we really need separate time stamps for each report?
1091 // Get our NTP as late as possible to avoid a race.
1092 uint32_t ntp_secs;
1093 uint32_t ntp_frac;
1094 clock_->CurrentNtp(ntp_secs, ntp_frac);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001095
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001096 // Delay since last received report.
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001097 uint32_t delaySinceLastReceivedSR = 0;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001098 if ((feedback_state.last_rr_ntp_secs != 0) ||
1099 (feedback_state.last_rr_ntp_frac != 0)) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001100 // Get the 16 lowest bits of seconds and the 16 highest bits of fractions.
1101 uint32_t now = ntp_secs & 0x0000FFFF;
Erik Språng61be2a42015-04-27 13:32:52 +02001102 now <<= 16;
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001103 now += (ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001104
Erik Språng61be2a42015-04-27 13:32:52 +02001105 uint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
1106 receiveTime <<= 16;
1107 receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001108
1109 delaySinceLastReceivedSR = now-receiveTime;
1110 }
1111 report_block->delaySinceLastSR = delaySinceLastReceivedSR;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001112 report_block->lastSR = feedback_state.remote_sr;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001113 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +00001114}
1115
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001116int32_t RTCPSender::SendToNetwork(const uint8_t* dataBuffer, size_t length) {
sprang86fd9ed2015-09-29 04:45:43 -07001117 if (transport_->SendRtcp(dataBuffer, length))
1118 return 0;
Erik Språng61be2a42015-04-27 13:32:52 +02001119 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001120}
1121
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001122void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
1123 assert(csrcs.size() <= kRtpCsrcSize);
Erik Språng242e22b2015-05-11 10:17:43 +02001124 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001125 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +00001126}
1127
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001128int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
1129 uint32_t name,
1130 const uint8_t* data,
1131 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +02001132 if (length % 4 != 0) {
1133 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
1134 return -1;
1135 }
Erik Språng242e22b2015-05-11 10:17:43 +02001136 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +00001137
Erik Språng242e22b2015-05-11 10:17:43 +02001138 SetFlag(kRtcpApp, true);
1139 app_sub_type_ = subType;
1140 app_name_ = name;
1141 app_data_.reset(new uint8_t[length]);
1142 app_length_ = length;
1143 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +02001144 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001145}
1146
Erik Språng61be2a42015-04-27 13:32:52 +02001147int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
Erik Språng242e22b2015-05-11 10:17:43 +02001148 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1149 memcpy(&xr_voip_metric_, VoIPMetric, sizeof(RTCPVoIPMetric));
niklase@google.com470e71d2011-07-07 08:21:25 +00001150
Erik Språng242e22b2015-05-11 10:17:43 +02001151 SetFlag(kRtcpXrVoipMetric, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001152 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001153}
1154
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001155void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +02001156 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1157 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001158}
1159
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00001160bool RTCPSender::RtcpXrReceiverReferenceTime() const {
Erik Språng242e22b2015-05-11 10:17:43 +02001161 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1162 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00001163}
1164
niklase@google.com470e71d2011-07-07 08:21:25 +00001165// no callbacks allowed inside this function
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001166int32_t RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
1167 uint32_t maxBitrateKbit) {
Erik Språng242e22b2015-05-11 10:17:43 +02001168 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +00001169
Erik Språng242e22b2015-05-11 10:17:43 +02001170 if (0 == tmmbr_help_.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit)) {
1171 SetFlag(kRtcpTmmbn, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001172 return 0;
1173 }
1174 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001175}
Erik Språng61be2a42015-04-27 13:32:52 +02001176
Erik Språng242e22b2015-05-11 10:17:43 +02001177void RTCPSender::SetFlag(RTCPPacketType type, bool is_volatile) {
1178 report_flags_.insert(ReportFlag(type, is_volatile));
1179}
1180
1181void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
1182 bool is_volatile) {
1183 for (RTCPPacketType type : types)
1184 SetFlag(type, is_volatile);
1185}
1186
1187bool RTCPSender::IsFlagPresent(RTCPPacketType type) const {
1188 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
1189}
1190
1191bool RTCPSender::ConsumeFlag(RTCPPacketType type, bool forced) {
1192 auto it = report_flags_.find(ReportFlag(type, false));
1193 if (it == report_flags_.end())
1194 return false;
1195 if (it->is_volatile || forced)
1196 report_flags_.erase((it));
1197 return true;
1198}
1199
1200bool RTCPSender::AllVolatileFlagsConsumed() const {
1201 for (const ReportFlag& flag : report_flags_) {
1202 if (flag.is_volatile)
1203 return false;
1204 }
1205 return true;
1206}
1207
sprang233bd872015-09-08 13:25:16 -07001208bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
sprang233bd872015-09-08 13:25:16 -07001209 class Sender : public rtcp::RtcpPacket::PacketReadyCallback {
1210 public:
Peter Boströmac547a62015-09-17 23:03:57 +02001211 Sender(Transport* transport)
1212 : transport_(transport), send_failure_(false) {}
sprang233bd872015-09-08 13:25:16 -07001213
1214 void OnPacketReady(uint8_t* data, size_t length) override {
pbos2d566682015-09-28 09:59:31 -07001215 if (!transport_->SendRtcp(data, length))
sprang233bd872015-09-08 13:25:16 -07001216 send_failure_ = true;
1217 }
1218
1219 Transport* const transport_;
sprang233bd872015-09-08 13:25:16 -07001220 bool send_failure_;
sprang86fd9ed2015-09-29 04:45:43 -07001221 } sender(transport_);
sprang233bd872015-09-08 13:25:16 -07001222
1223 uint8_t buffer[IP_PACKET_SIZE];
1224 return packet.BuildExternalBuffer(buffer, IP_PACKET_SIZE, &sender) &&
1225 !sender.send_failure_;
1226}
1227
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001228} // namespace webrtc