blob: 99292994c1f5b34f3358901f9d84d4b96bdcaa89 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000011#include "webrtc/modules/rtp_rtcp/source/rtcp_sender.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000013#include <assert.h> // assert
14#include <stdlib.h> // rand
stefan@webrtc.org9354cc92012-06-07 08:10:14 +000015#include <string.h> // memcpy
niklase@google.com470e71d2011-07-07 08:21:25 +000016
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000017#include <algorithm> // min
Erik Språng61be2a42015-04-27 13:32:52 +020018#include <limits> // max
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000019
Erik Språng61be2a42015-04-27 13:32:52 +020020#include "webrtc/base/checks.h"
Peter Boströmebc0b4e2015-10-28 16:39:33 +010021#include "webrtc/base/logging.h"
tommie4f96502015-10-20 23:00:48 -070022#include "webrtc/base/trace_event.h"
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000023#include "webrtc/common_types.h"
sprang@webrtc.org779c3d12015-03-17 16:42:49 +000024#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
danilchap0219c9b2015-11-18 05:56:53 -080025#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/app.h"
danilchap50c51362015-11-22 09:03:11 -080026#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/bye.h"
sprang233bd872015-09-08 13:25:16 -070027#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
tommie4f96502015-10-20 23:00:48 -070028#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010029#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000030
niklase@google.com470e71d2011-07-07 08:21:25 +000031namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000032
33using RTCPUtility::RTCPCnameInformation;
34
Erik Språng61be2a42015-04-27 13:32:52 +020035NACKStringBuilder::NACKStringBuilder()
Erik Språng242e22b2015-05-11 10:17:43 +020036 : stream_(""), count_(0), prevNack_(0), consecutive_(false) {
edjee@google.com79b02892013-04-04 19:43:34 +000037}
38
pbos@webrtc.orgf3e4cee2013-07-31 15:17:19 +000039NACKStringBuilder::~NACKStringBuilder() {}
40
pbos@webrtc.org2f446732013-04-08 11:08:41 +000041void NACKStringBuilder::PushNACK(uint16_t nack)
edjee@google.com79b02892013-04-04 19:43:34 +000042{
Erik Språng242e22b2015-05-11 10:17:43 +020043 if (count_ == 0) {
44 stream_ << nack;
45 } else if (nack == prevNack_ + 1) {
46 consecutive_ = true;
Erik Språng61be2a42015-04-27 13:32:52 +020047 } else {
Erik Språng242e22b2015-05-11 10:17:43 +020048 if (consecutive_) {
49 stream_ << "-" << prevNack_;
50 consecutive_ = false;
edjee@google.com79b02892013-04-04 19:43:34 +000051 }
Erik Språng242e22b2015-05-11 10:17:43 +020052 stream_ << "," << nack;
Erik Språng61be2a42015-04-27 13:32:52 +020053 }
Erik Språng242e22b2015-05-11 10:17:43 +020054 count_++;
55 prevNack_ = nack;
edjee@google.com79b02892013-04-04 19:43:34 +000056}
57
Erik Språng61be2a42015-04-27 13:32:52 +020058std::string NACKStringBuilder::GetResult() {
Erik Språng242e22b2015-05-11 10:17:43 +020059 if (consecutive_) {
60 stream_ << "-" << prevNack_;
61 consecutive_ = false;
Erik Språng61be2a42015-04-27 13:32:52 +020062 }
Erik Språng242e22b2015-05-11 10:17:43 +020063 return stream_.str();
edjee@google.com79b02892013-04-04 19:43:34 +000064}
65
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000066RTCPSender::FeedbackState::FeedbackState()
67 : send_payload_type(0),
68 frequency_hz(0),
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +000069 packets_sent(0),
70 media_bytes_sent(0),
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000071 send_bitrate(0),
72 last_rr_ntp_secs(0),
73 last_rr_ntp_frac(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000074 remote_sr(0),
Erik Språng61be2a42015-04-27 13:32:52 +020075 has_last_xr_rr(false),
76 module(nullptr) {
77}
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000078
Erik Språng242e22b2015-05-11 10:17:43 +020079struct RTCPSender::RtcpContext {
80 RtcpContext(const FeedbackState& feedback_state,
81 int32_t nack_size,
82 const uint16_t* nack_list,
83 bool repeat,
84 uint64_t picture_id,
85 uint8_t* buffer,
86 uint32_t buffer_size)
87 : feedback_state(feedback_state),
88 nack_size(nack_size),
89 nack_list(nack_list),
90 repeat(repeat),
91 picture_id(picture_id),
92 buffer(buffer),
93 buffer_size(buffer_size),
94 ntp_sec(0),
95 ntp_frac(0),
Erik Språng242e22b2015-05-11 10:17:43 +020096 position(0) {}
97
98 uint8_t* AllocateData(uint32_t bytes) {
henrikg91d6ede2015-09-17 00:24:34 -070099 RTC_DCHECK_LE(position + bytes, buffer_size);
Erik Språng242e22b2015-05-11 10:17:43 +0200100 uint8_t* ptr = &buffer[position];
101 position += bytes;
102 return ptr;
103 }
104
105 const FeedbackState& feedback_state;
106 int32_t nack_size;
107 const uint16_t* nack_list;
108 bool repeat;
109 uint64_t picture_id;
110 uint8_t* buffer;
111 uint32_t buffer_size;
112 uint32_t ntp_sec;
113 uint32_t ntp_frac;
Erik Språng242e22b2015-05-11 10:17:43 +0200114 uint32_t position;
115};
116
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200117// TODO(sprang): Once all builders use RtcpPacket, call SendToNetwork() here.
118class RTCPSender::PacketBuiltCallback
119 : public rtcp::RtcpPacket::PacketReadyCallback {
120 public:
121 PacketBuiltCallback(RtcpContext* context) : context_(context) {}
122 virtual ~PacketBuiltCallback() {}
123 void OnPacketReady(uint8_t* data, size_t length) override {
124 context_->position += length;
125 }
Erik Språng72aa9a62015-07-31 16:16:02 +0200126 bool BuildPacket(const rtcp::RtcpPacket& packet) {
127 return packet.BuildExternalBuffer(
128 &context_->buffer[context_->position],
129 context_->buffer_size - context_->position, this);
130 }
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200131
132 private:
133 RtcpContext* const context_;
134};
135
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000136RTCPSender::RTCPSender(
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000137 bool audio,
138 Clock* clock,
139 ReceiveStatistics* receive_statistics,
sprang86fd9ed2015-09-29 04:45:43 -0700140 RtcpPacketTypeCounterObserver* packet_type_counter_observer,
141 Transport* outgoing_transport)
Peter Boströmac547a62015-09-17 23:03:57 +0200142 : audio_(audio),
Erik Språng242e22b2015-05-11 10:17:43 +0200143 clock_(clock),
pbosda903ea2015-10-02 02:36:56 -0700144 method_(RtcpMode::kOff),
sprang86fd9ed2015-09-29 04:45:43 -0700145 transport_(outgoing_transport),
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_));
sprang86fd9ed2015-09-29 04:45:43 -0700177 RTC_DCHECK(transport_ != nullptr);
Erik Språng242e22b2015-05-11 10:17:43 +0200178
179 builders_[kRtcpSr] = &RTCPSender::BuildSR;
180 builders_[kRtcpRr] = &RTCPSender::BuildRR;
Erik Språng0ea42d32015-06-25 14:46:16 +0200181 builders_[kRtcpSdes] = &RTCPSender::BuildSDES;
Erik Språng242e22b2015-05-11 10:17:43 +0200182 builders_[kRtcpPli] = &RTCPSender::BuildPLI;
183 builders_[kRtcpFir] = &RTCPSender::BuildFIR;
184 builders_[kRtcpSli] = &RTCPSender::BuildSLI;
185 builders_[kRtcpRpsi] = &RTCPSender::BuildRPSI;
186 builders_[kRtcpRemb] = &RTCPSender::BuildREMB;
187 builders_[kRtcpBye] = &RTCPSender::BuildBYE;
188 builders_[kRtcpApp] = &RTCPSender::BuildAPP;
189 builders_[kRtcpTmmbr] = &RTCPSender::BuildTMMBR;
190 builders_[kRtcpTmmbn] = &RTCPSender::BuildTMMBN;
191 builders_[kRtcpNack] = &RTCPSender::BuildNACK;
192 builders_[kRtcpXrVoipMetric] = &RTCPSender::BuildVoIPMetric;
193 builders_[kRtcpXrReceiverReferenceTime] =
194 &RTCPSender::BuildReceiverReferenceTime;
195 builders_[kRtcpXrDlrrReportBlock] = &RTCPSender::BuildDlrr;
niklase@google.com470e71d2011-07-07 08:21:25 +0000196}
197
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000198RTCPSender::~RTCPSender() {
niklase@google.com470e71d2011-07-07 08:21:25 +0000199}
200
pbosda903ea2015-10-02 02:36:56 -0700201RtcpMode RTCPSender::Status() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200202 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
203 return method_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000204}
205
pbosda903ea2015-10-02 02:36:56 -0700206void RTCPSender::SetRTCPStatus(RtcpMode method) {
Erik Språng242e22b2015-05-11 10:17:43 +0200207 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
208 method_ = method;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000209
pbosda903ea2015-10-02 02:36:56 -0700210 if (method == RtcpMode::kOff)
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000211 return;
Erik Språng242e22b2015-05-11 10:17:43 +0200212 next_time_to_send_rtcp_ =
213 clock_->TimeInMilliseconds() +
214 (audio_ ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000215}
216
Erik Språng61be2a42015-04-27 13:32:52 +0200217bool RTCPSender::Sending() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200218 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
219 return sending_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000220}
221
Erik Språng61be2a42015-04-27 13:32:52 +0200222int32_t RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
223 bool sending) {
224 bool sendRTCPBye = false;
225 {
Erik Språng242e22b2015-05-11 10:17:43 +0200226 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000227
pbosda903ea2015-10-02 02:36:56 -0700228 if (method_ != RtcpMode::kOff) {
Erik Språng242e22b2015-05-11 10:17:43 +0200229 if (sending == false && sending_ == true) {
Erik Språng61be2a42015-04-27 13:32:52 +0200230 // Trigger RTCP bye
231 sendRTCPBye = true;
232 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000233 }
Erik Språng242e22b2015-05-11 10:17:43 +0200234 sending_ = sending;
Erik Språng61be2a42015-04-27 13:32:52 +0200235 }
236 if (sendRTCPBye)
237 return SendRTCP(feedback_state, kRtcpBye);
238 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000239}
240
Erik Språng61be2a42015-04-27 13:32:52 +0200241bool RTCPSender::REMB() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200242 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
243 return remb_enabled_;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000244}
245
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000246void RTCPSender::SetREMBStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200247 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
248 remb_enabled_ = enable;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000249}
250
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000251void RTCPSender::SetREMBData(uint32_t bitrate,
252 const std::vector<uint32_t>& ssrcs) {
Erik Språng242e22b2015-05-11 10:17:43 +0200253 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
254 remb_bitrate_ = bitrate;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000255 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000256
Erik Språng242e22b2015-05-11 10:17:43 +0200257 if (remb_enabled_)
258 SetFlag(kRtcpRemb, false);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000259 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
260 // throttled by the caller.
Erik Språng242e22b2015-05-11 10:17:43 +0200261 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000262}
263
Erik Språng61be2a42015-04-27 13:32:52 +0200264bool RTCPSender::TMMBR() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200265 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
266 return IsFlagPresent(RTCPPacketType::kRtcpTmmbr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000267}
268
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000269void RTCPSender::SetTMMBRStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200270 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
271 if (enable) {
272 SetFlag(RTCPPacketType::kRtcpTmmbr, false);
273 } else {
274 ConsumeFlag(RTCPPacketType::kRtcpTmmbr, true);
275 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000276}
277
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000278void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
Erik Språng242e22b2015-05-11 10:17:43 +0200279 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000280 start_timestamp_ = start_timestamp;
281}
282
283void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
284 int64_t capture_time_ms) {
Erik Språng242e22b2015-05-11 10:17:43 +0200285 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000286 last_rtp_timestamp_ = rtp_timestamp;
287 if (capture_time_ms < 0) {
288 // We don't currently get a capture time from VoiceEngine.
Erik Språng242e22b2015-05-11 10:17:43 +0200289 last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000290 } else {
291 last_frame_capture_time_ms_ = capture_time_ms;
292 }
293}
294
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000295void RTCPSender::SetSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200296 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000297
Erik Språng242e22b2015-05-11 10:17:43 +0200298 if (ssrc_ != 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200299 // not first SetSSRC, probably due to a collision
300 // schedule a new RTCP report
301 // make sure that we send a RTP packet
Erik Språng242e22b2015-05-11 10:17:43 +0200302 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
Erik Språng61be2a42015-04-27 13:32:52 +0200303 }
Erik Språng242e22b2015-05-11 10:17:43 +0200304 ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000305}
306
Erik Språng61be2a42015-04-27 13:32:52 +0200307void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200308 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
309 remote_ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000310}
311
Peter Boström9ba52f82015-06-01 14:12:28 +0200312int32_t RTCPSender::SetCNAME(const char* c_name) {
313 if (!c_name)
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000314 return -1;
315
henrikg91d6ede2015-09-17 00:24:34 -0700316 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
Erik Språng242e22b2015-05-11 10:17:43 +0200317 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200318 cname_ = c_name;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000319 return 0;
320}
321
Erik Språng0ea42d32015-06-25 14:46:16 +0200322int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC, const char* c_name) {
323 assert(c_name);
henrikg91d6ede2015-09-17 00:24:34 -0700324 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
Erik Språng242e22b2015-05-11 10:17:43 +0200325 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200326 if (csrc_cnames_.size() >= kRtpCsrcSize)
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000327 return -1;
Erik Språng0ea42d32015-06-25 14:46:16 +0200328
329 csrc_cnames_[SSRC] = c_name;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000330 return 0;
331}
332
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000333int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
Erik Språng242e22b2015-05-11 10:17:43 +0200334 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200335 auto it = csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000336
Erik Språng242e22b2015-05-11 10:17:43 +0200337 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000338 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200339
Erik Språng242e22b2015-05-11 10:17:43 +0200340 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000341 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000342}
343
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000344bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
niklase@google.com470e71d2011-07-07 08:21:25 +0000345/*
346 For audio we use a fix 5 sec interval
347
348 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000349 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
350 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000351
352
353From RFC 3550
354
355 MAX RTCP BW is 5% if the session BW
356 A send report is approximately 65 bytes inc CNAME
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000357 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000358
359 The RECOMMENDED value for the reduced minimum in seconds is 360
360 divided by the session bandwidth in kilobits/second. This minimum
361 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
362
363 If the participant has not yet sent an RTCP packet (the variable
364 initial is true), the constant Tmin is set to 2.5 seconds, else it
365 is set to 5 seconds.
366
367 The interval between RTCP packets is varied randomly over the
368 range [0.5,1.5] times the calculated interval to avoid unintended
369 synchronization of all participants
370
371 if we send
372 If the participant is a sender (we_sent true), the constant C is
373 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
374 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
375 number of senders.
376
377 if we receive only
378 If we_sent is not true, the constant C is set
379 to the average RTCP packet size divided by 75% of the RTCP
380 bandwidth. The constant n is set to the number of receivers
381 (members - senders). If the number of senders is greater than
382 25%, senders and receivers are treated together.
383
384 reconsideration NOT required for peer-to-peer
385 "timer reconsideration" is
386 employed. This algorithm implements a simple back-off mechanism
387 which causes users to hold back RTCP packet transmission if the
388 group sizes are increasing.
389
390 n = number of members
391 C = avg_size/(rtcpBW/4)
392
393 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
394
395 4. The calculated interval T is set to a number uniformly distributed
396 between 0.5 and 1.5 times the deterministic calculated interval.
397
398 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
399 for the fact that the timer reconsideration algorithm converges to
400 a value of the RTCP bandwidth below the intended average
401*/
402
Erik Språng242e22b2015-05-11 10:17:43 +0200403 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000404
Erik Språng242e22b2015-05-11 10:17:43 +0200405 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
xians@webrtc.org8738d272011-11-25 13:43:53 +0000406
pbosda903ea2015-10-02 02:36:56 -0700407 if (method_ == RtcpMode::kOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000408 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000409
Erik Språng242e22b2015-05-11 10:17:43 +0200410 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200411 // for video key-frames we want to send the RTCP before the large key-frame
412 // if we have a 100 ms margin
413 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
414 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000415
Erik Språng242e22b2015-05-11 10:17:43 +0200416 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200417 return true;
418 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200419 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200420 // wrap
421 return true;
422 }
423 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000424}
425
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000426int64_t RTCPSender::SendTimeOfSendReport(uint32_t sendReport) {
Erik Språng242e22b2015-05-11 10:17:43 +0200427 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000428
Erik Språng61be2a42015-04-27 13:32:52 +0200429 // This is only saved when we are the sender
Erik Språng242e22b2015-05-11 10:17:43 +0200430 if ((last_send_report_[0] == 0) || (sendReport == 0)) {
Erik Språng61be2a42015-04-27 13:32:52 +0200431 return 0; // will be ignored
432 } else {
433 for (int i = 0; i < RTCP_NUMBER_OF_SR; ++i) {
Erik Språng242e22b2015-05-11 10:17:43 +0200434 if (last_send_report_[i] == sendReport)
435 return last_rtcp_time_[i];
niklase@google.com470e71d2011-07-07 08:21:25 +0000436 }
Erik Språng61be2a42015-04-27 13:32:52 +0200437 }
438 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000439}
440
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000441bool RTCPSender::SendTimeOfXrRrReport(uint32_t mid_ntp,
442 int64_t* time_ms) const {
Erik Språng242e22b2015-05-11 10:17:43 +0200443 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000444
445 if (last_xr_rr_.empty()) {
446 return false;
447 }
448 std::map<uint32_t, int64_t>::const_iterator it = last_xr_rr_.find(mid_ntp);
449 if (it == last_xr_rr_.end()) {
450 return false;
451 }
452 *time_ms = it->second;
453 return true;
454}
455
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200456int32_t RTCPSender::AddReportBlock(const RTCPReportBlock& report_block) {
457 if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000458 LOG(LS_WARNING) << "Too many report blocks.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000459 return -1;
460 }
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200461 rtcp::ReportBlock* block = &report_blocks_[report_block.remoteSSRC];
462 block->To(report_block.remoteSSRC);
463 block->WithFractionLost(report_block.fractionLost);
danilchapdf948f02015-11-13 03:03:13 -0800464 if (!block->WithCumulativeLost(report_block.cumulativeLost)) {
465 LOG(LS_WARNING) << "Cumulative lost is oversized.";
466 return -1;
467 }
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200468 block->WithExtHighestSeqNum(report_block.extendedHighSeqNum);
469 block->WithJitter(report_block.jitter);
470 block->WithLastSr(report_block.lastSR);
471 block->WithDelayLastSr(report_block.delaySinceLastSR);
472
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000473 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000474}
475
Erik Språng242e22b2015-05-11 10:17:43 +0200476RTCPSender::BuildResult RTCPSender::BuildSR(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200477 for (int i = (RTCP_NUMBER_OF_SR - 2); i >= 0; i--) {
478 // shift old
Erik Språng242e22b2015-05-11 10:17:43 +0200479 last_send_report_[i + 1] = last_send_report_[i];
480 last_rtcp_time_[i + 1] = last_rtcp_time_[i];
Erik Språng61be2a42015-04-27 13:32:52 +0200481 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000482
Erik Språng242e22b2015-05-11 10:17:43 +0200483 last_rtcp_time_[0] = Clock::NtpToMs(ctx->ntp_sec, ctx->ntp_frac);
484 last_send_report_[0] = (ctx->ntp_sec << 16) + (ctx->ntp_frac >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000485
Erik Språng61be2a42015-04-27 13:32:52 +0200486 // The timestamp of this RTCP packet should be estimated as the timestamp of
487 // the frame being captured at this moment. We are calculating that
488 // timestamp as the last frame's timestamp + the time since the last frame
489 // was captured.
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200490 uint32_t rtp_timestamp =
491 start_timestamp_ + last_rtp_timestamp_ +
492 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) *
493 (ctx->feedback_state.frequency_hz / 1000);
niklase@google.com470e71d2011-07-07 08:21:25 +0000494
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200495 rtcp::SenderReport report;
496 report.From(ssrc_);
497 report.WithNtpSec(ctx->ntp_sec);
498 report.WithNtpFrac(ctx->ntp_frac);
499 report.WithRtpTimestamp(rtp_timestamp);
500 report.WithPacketCount(ctx->feedback_state.packets_sent);
501 report.WithOctetCount(ctx->feedback_state.media_bytes_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000502
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200503 for (auto it : report_blocks_)
504 report.WithReportBlock(it.second);
niklase@google.com470e71d2011-07-07 08:21:25 +0000505
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200506 PacketBuiltCallback callback(ctx);
Erik Språng72aa9a62015-07-31 16:16:02 +0200507 if (!callback.BuildPacket(report))
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200508 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000509
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200510 report_blocks_.clear();
Erik Språng242e22b2015-05-11 10:17:43 +0200511 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000512}
513
Erik Språng0ea42d32015-06-25 14:46:16 +0200514RTCPSender::BuildResult RTCPSender::BuildSDES(RtcpContext* ctx) {
515 size_t length_cname = cname_.length();
henrikg91d6ede2015-09-17 00:24:34 -0700516 RTC_CHECK_LT(length_cname, static_cast<size_t>(RTCP_CNAME_SIZE));
niklase@google.com470e71d2011-07-07 08:21:25 +0000517
Erik Språng0ea42d32015-06-25 14:46:16 +0200518 rtcp::Sdes sdes;
519 sdes.WithCName(ssrc_, cname_);
520
521 for (const auto it : csrc_cnames_)
522 sdes.WithCName(it.first, it.second);
523
524 PacketBuiltCallback callback(ctx);
Erik Språng72aa9a62015-07-31 16:16:02 +0200525 if (!callback.BuildPacket(sdes))
Erik Språng242e22b2015-05-11 10:17:43 +0200526 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000527
Erik Språng242e22b2015-05-11 10:17:43 +0200528 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000529}
530
Erik Språng242e22b2015-05-11 10:17:43 +0200531RTCPSender::BuildResult RTCPSender::BuildRR(RtcpContext* ctx) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200532 rtcp::ReceiverReport report;
533 report.From(ssrc_);
534 for (auto it : report_blocks_)
535 report.WithReportBlock(it.second);
536
537 PacketBuiltCallback callback(ctx);
Erik Språng72aa9a62015-07-31 16:16:02 +0200538 if (!callback.BuildPacket(report))
Erik Språng242e22b2015-05-11 10:17:43 +0200539 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200540
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200541 report_blocks_.clear();
Erik Språng242e22b2015-05-11 10:17:43 +0200542
543 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000544}
545
Erik Språng242e22b2015-05-11 10:17:43 +0200546RTCPSender::BuildResult RTCPSender::BuildPLI(RtcpContext* ctx) {
Erik Språng72aa9a62015-07-31 16:16:02 +0200547 rtcp::Pli pli;
548 pli.From(ssrc_);
549 pli.To(remote_ssrc_);
550
551 PacketBuiltCallback callback(ctx);
552 if (!callback.BuildPacket(pli))
Erik Språng242e22b2015-05-11 10:17:43 +0200553 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200554
Erik Språng242e22b2015-05-11 10:17:43 +0200555 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
556 "RTCPSender::PLI");
557 ++packet_type_counter_.pli_packets;
558 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
559 ssrc_, packet_type_counter_.pli_packets);
560
561 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +0200562}
563
Erik Språng242e22b2015-05-11 10:17:43 +0200564RTCPSender::BuildResult RTCPSender::BuildFIR(RtcpContext* ctx) {
Erik Språng242e22b2015-05-11 10:17:43 +0200565 if (!ctx->repeat)
sprang62dae192015-08-05 02:35:35 -0700566 ++sequence_number_fir_; // Do not increase if repetition.
niklase@google.com470e71d2011-07-07 08:21:25 +0000567
sprang62dae192015-08-05 02:35:35 -0700568 rtcp::Fir fir;
569 fir.From(ssrc_);
570 fir.To(remote_ssrc_);
571 fir.WithCommandSeqNum(sequence_number_fir_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000572
sprang62dae192015-08-05 02:35:35 -0700573 PacketBuiltCallback callback(ctx);
574 if (!callback.BuildPacket(fir))
575 return BuildResult::kTruncated;
Erik Språng242e22b2015-05-11 10:17:43 +0200576
577 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
578 "RTCPSender::FIR");
579 ++packet_type_counter_.fir_packets;
580 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
581 ssrc_, packet_type_counter_.fir_packets);
582
583 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000584}
585
586/*
587 0 1 2 3
588 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
589 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
590 | First | Number | PictureID |
591 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
592*/
Erik Språng242e22b2015-05-11 10:17:43 +0200593RTCPSender::BuildResult RTCPSender::BuildSLI(RtcpContext* ctx) {
sprang0365a272015-08-11 01:02:37 -0700594 rtcp::Sli sli;
595 sli.From(ssrc_);
596 sli.To(remote_ssrc_);
597 // Crop picture id to 6 least significant bits.
598 sli.WithPictureId(ctx->picture_id & 0x3F);
599 sli.WithFirstMb(0);
600 sli.WithNumberOfMb(0x1FFF); // 13 bits, only ones for now.
601
602 PacketBuiltCallback callback(ctx);
603 if (!callback.BuildPacket(sli))
Erik Språng242e22b2015-05-11 10:17:43 +0200604 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000605
Erik Språng242e22b2015-05-11 10:17:43 +0200606 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000607}
608
609/*
610 0 1 2 3
611 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
612 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
613 | PB |0| Payload Type| Native RPSI bit string |
614 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
615 | defined per codec ... | Padding (0) |
616 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
617*/
618/*
619* Note: not generic made for VP8
620*/
Erik Språng242e22b2015-05-11 10:17:43 +0200621RTCPSender::BuildResult RTCPSender::BuildRPSI(RtcpContext* ctx) {
622 if (ctx->feedback_state.send_payload_type == 0xFF)
623 return BuildResult::kError;
624
sprangcf7f54d2015-08-13 04:37:42 -0700625 rtcp::Rpsi rpsi;
626 rpsi.From(ssrc_);
627 rpsi.To(remote_ssrc_);
628 rpsi.WithPayloadType(ctx->feedback_state.send_payload_type);
629 rpsi.WithPictureId(ctx->picture_id);
630
631 PacketBuiltCallback callback(ctx);
632 if (!callback.BuildPacket(rpsi))
Erik Språng242e22b2015-05-11 10:17:43 +0200633 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000634
Erik Språng242e22b2015-05-11 10:17:43 +0200635 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000636}
637
Erik Språng242e22b2015-05-11 10:17:43 +0200638RTCPSender::BuildResult RTCPSender::BuildREMB(RtcpContext* ctx) {
sprangdd4edc52015-08-21 04:21:51 -0700639 rtcp::Remb remb;
640 remb.From(ssrc_);
641 for (uint32_t ssrc : remb_ssrcs_)
642 remb.AppliesTo(ssrc);
643 remb.WithBitrateBps(remb_bitrate_);
644
645 PacketBuiltCallback callback(ctx);
646 if (!callback.BuildPacket(remb))
Erik Språng242e22b2015-05-11 10:17:43 +0200647 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200648
Erik Språng242e22b2015-05-11 10:17:43 +0200649 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
650 "RTCPSender::REMB");
651
652 return BuildResult::kSuccess;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000653}
654
Erik Språng61be2a42015-04-27 13:32:52 +0200655void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
Erik Språng242e22b2015-05-11 10:17:43 +0200656 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
657 tmmbr_send_ = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000658}
659
Erik Språng242e22b2015-05-11 10:17:43 +0200660RTCPSender::BuildResult RTCPSender::BuildTMMBR(RtcpContext* ctx) {
661 if (ctx->feedback_state.module == NULL)
662 return BuildResult::kError;
Erik Språng61be2a42015-04-27 13:32:52 +0200663 // Before sending the TMMBR check the received TMMBN, only an owner is
664 // allowed to raise the bitrate:
665 // * If the sender is an owner of the TMMBN -> send TMMBR
666 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000667
Erik Språng61be2a42015-04-27 13:32:52 +0200668 // get current bounding set from RTCP receiver
669 bool tmmbrOwner = false;
670 // store in candidateSet, allocates one extra slot
Erik Språng242e22b2015-05-11 10:17:43 +0200671 TMMBRSet* candidateSet = tmmbr_help_.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000672
Erik Språng242e22b2015-05-11 10:17:43 +0200673 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
674 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
Erik Språng61be2a42015-04-27 13:32:52 +0200675 // since RTCPreceiver is not doing the reverse we should be fine
676 int32_t lengthOfBoundingSet =
Erik Språng242e22b2015-05-11 10:17:43 +0200677 ctx->feedback_state.module->BoundingSet(tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +0000678
Erik Språng61be2a42015-04-27 13:32:52 +0200679 if (lengthOfBoundingSet > 0) {
680 for (int32_t i = 0; i < lengthOfBoundingSet; i++) {
Erik Språng242e22b2015-05-11 10:17:43 +0200681 if (candidateSet->Tmmbr(i) == tmmbr_send_ &&
682 candidateSet->PacketOH(i) == packet_oh_send_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200683 // do not send the same tuple
Erik Språng242e22b2015-05-11 10:17:43 +0200684 return BuildResult::kAborted;
Erik Språng61be2a42015-04-27 13:32:52 +0200685 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000686 }
Erik Språng61be2a42015-04-27 13:32:52 +0200687 if (!tmmbrOwner) {
688 // use received bounding set as candidate set
689 // add current tuple
Erik Språng242e22b2015-05-11 10:17:43 +0200690 candidateSet->SetEntry(lengthOfBoundingSet, tmmbr_send_, packet_oh_send_,
691 ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200692 int numCandidates = lengthOfBoundingSet + 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000693
Erik Språng61be2a42015-04-27 13:32:52 +0200694 // find bounding set
695 TMMBRSet* boundingSet = NULL;
Erik Språng242e22b2015-05-11 10:17:43 +0200696 int numBoundingSet = tmmbr_help_.FindTMMBRBoundingSet(boundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200697 if (numBoundingSet > 0 || numBoundingSet <= numCandidates)
Erik Språng242e22b2015-05-11 10:17:43 +0200698 tmmbrOwner = tmmbr_help_.IsOwner(ssrc_, numBoundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200699 if (!tmmbrOwner) {
700 // did not enter bounding set, no meaning to send this request
Erik Språng242e22b2015-05-11 10:17:43 +0200701 return BuildResult::kAborted;
Erik Språng61be2a42015-04-27 13:32:52 +0200702 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000703 }
Erik Språng61be2a42015-04-27 13:32:52 +0200704 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000705
Erik Språng242e22b2015-05-11 10:17:43 +0200706 if (tmmbr_send_) {
sprang81a3e602015-08-21 05:30:11 -0700707 rtcp::Tmmbr tmmbr;
708 tmmbr.From(ssrc_);
709 tmmbr.To(remote_ssrc_);
710 tmmbr.WithBitrateKbps(tmmbr_send_);
711 tmmbr.WithOverhead(packet_oh_send_);
712
713 PacketBuiltCallback callback(ctx);
714 if (!callback.BuildPacket(tmmbr))
Erik Språng242e22b2015-05-11 10:17:43 +0200715 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200716 }
Erik Språng242e22b2015-05-11 10:17:43 +0200717 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +0200718}
719
Erik Språng242e22b2015-05-11 10:17:43 +0200720RTCPSender::BuildResult RTCPSender::BuildTMMBN(RtcpContext* ctx) {
721 TMMBRSet* boundingSet = tmmbr_help_.BoundingSetToSend();
Erik Språng61be2a42015-04-27 13:32:52 +0200722 if (boundingSet == NULL)
Erik Språng242e22b2015-05-11 10:17:43 +0200723 return BuildResult::kError;
Erik Språng61be2a42015-04-27 13:32:52 +0200724
sprangd83df502015-08-27 01:05:08 -0700725 rtcp::Tmmbn tmmbn;
726 tmmbn.From(ssrc_);
727 for (uint32_t i = 0; i < boundingSet->lengthOfSet(); i++) {
728 if (boundingSet->Tmmbr(i) > 0) {
729 tmmbn.WithTmmbr(boundingSet->Ssrc(i), boundingSet->Tmmbr(i),
730 boundingSet->PacketOH(i));
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000731 }
Erik Språng61be2a42015-04-27 13:32:52 +0200732 }
sprangd83df502015-08-27 01:05:08 -0700733
734 PacketBuiltCallback callback(ctx);
735 if (!callback.BuildPacket(tmmbn))
736 return BuildResult::kTruncated;
Erik Språng242e22b2015-05-11 10:17:43 +0200737
738 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000739}
740
Erik Språng242e22b2015-05-11 10:17:43 +0200741RTCPSender::BuildResult RTCPSender::BuildAPP(RtcpContext* ctx) {
Erik Språng521875a2015-09-01 10:11:16 +0200742 rtcp::App app;
743 app.From(ssrc_);
744 app.WithSubType(app_sub_type_);
745 app.WithName(app_name_);
746 app.WithData(app_data_.get(), app_length_);
747
748 PacketBuiltCallback callback(ctx);
749 if (!callback.BuildPacket(app))
Erik Språng242e22b2015-05-11 10:17:43 +0200750 return BuildResult::kTruncated;
Erik Språng242e22b2015-05-11 10:17:43 +0200751
752 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +0200753}
754
Erik Språng242e22b2015-05-11 10:17:43 +0200755RTCPSender::BuildResult RTCPSender::BuildNACK(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200756 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200757 if (ctx->position + 16 >= IP_PACKET_SIZE) {
Erik Språng61be2a42015-04-27 13:32:52 +0200758 LOG(LS_WARNING) << "Failed to build NACK.";
Erik Språng242e22b2015-05-11 10:17:43 +0200759 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200760 }
761
Erik Språng242e22b2015-05-11 10:17:43 +0200762 // int size, uint16_t* nack_list
Erik Språng61be2a42015-04-27 13:32:52 +0200763 // add nack list
764 uint8_t FMT = 1;
Erik Språng242e22b2015-05-11 10:17:43 +0200765 *ctx->AllocateData(1) = 0x80 + FMT;
766 *ctx->AllocateData(1) = 205;
Erik Språng61be2a42015-04-27 13:32:52 +0200767
Erik Språng242e22b2015-05-11 10:17:43 +0200768 *ctx->AllocateData(1) = 0;
769 int nack_size_pos_ = ctx->position;
770 *ctx->AllocateData(1) = 3; // setting it to one kNACK signal as default
Erik Språng61be2a42015-04-27 13:32:52 +0200771
772 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200773 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200774
775 // Add the remote SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200776 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200777
778 // Build NACK bitmasks and write them to the RTCP message.
779 // The nack list should be sorted and not contain duplicates if one
780 // wants to build the smallest rtcp nack packet.
781 int numOfNackFields = 0;
782 int maxNackFields =
Erik Språng242e22b2015-05-11 10:17:43 +0200783 std::min<int>(kRtcpMaxNackFields, (IP_PACKET_SIZE - ctx->position) / 4);
Erik Språng61be2a42015-04-27 13:32:52 +0200784 int i = 0;
Erik Språng242e22b2015-05-11 10:17:43 +0200785 while (i < ctx->nack_size && numOfNackFields < maxNackFields) {
786 uint16_t nack = ctx->nack_list[i++];
Erik Språng61be2a42015-04-27 13:32:52 +0200787 uint16_t bitmask = 0;
Erik Språng242e22b2015-05-11 10:17:43 +0200788 while (i < ctx->nack_size) {
789 int shift = static_cast<uint16_t>(ctx->nack_list[i] - nack) - 1;
Erik Språng61be2a42015-04-27 13:32:52 +0200790 if (shift >= 0 && shift <= 15) {
791 bitmask |= (1 << shift);
792 ++i;
793 } else {
794 break;
795 }
796 }
797 // Write the sequence number and the bitmask to the packet.
Erik Språng242e22b2015-05-11 10:17:43 +0200798 assert(ctx->position + 4 < IP_PACKET_SIZE);
799 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2), nack);
800 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2), bitmask);
Erik Språng61be2a42015-04-27 13:32:52 +0200801 numOfNackFields++;
802 }
Erik Språng242e22b2015-05-11 10:17:43 +0200803 ctx->buffer[nack_size_pos_] = static_cast<uint8_t>(2 + numOfNackFields);
Erik Språng61be2a42015-04-27 13:32:52 +0200804
Erik Språng242e22b2015-05-11 10:17:43 +0200805 if (i != ctx->nack_size)
Erik Språng61be2a42015-04-27 13:32:52 +0200806 LOG(LS_WARNING) << "Nack list too large for one packet.";
807
808 // Report stats.
809 NACKStringBuilder stringBuilder;
810 for (int idx = 0; idx < i; ++idx) {
Erik Språng242e22b2015-05-11 10:17:43 +0200811 stringBuilder.PushNACK(ctx->nack_list[idx]);
812 nack_stats_.ReportRequest(ctx->nack_list[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +0200813 }
Erik Språng61be2a42015-04-27 13:32:52 +0200814 packet_type_counter_.nack_requests = nack_stats_.requests();
815 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +0200816
817 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
818 "RTCPSender::NACK", "nacks",
819 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
820 ++packet_type_counter_.nack_packets;
821 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
822 ssrc_, packet_type_counter_.nack_packets);
823
824 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +0200825}
826
Erik Språng242e22b2015-05-11 10:17:43 +0200827RTCPSender::BuildResult RTCPSender::BuildBYE(RtcpContext* ctx) {
sprangd8ee4f92015-08-24 03:25:19 -0700828 rtcp::Bye bye;
829 bye.From(ssrc_);
830 for (uint32_t csrc : csrcs_)
831 bye.WithCsrc(csrc);
832
833 PacketBuiltCallback callback(ctx);
834 if (!callback.BuildPacket(bye))
Erik Språng242e22b2015-05-11 10:17:43 +0200835 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000836
Erik Språng242e22b2015-05-11 10:17:43 +0200837 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000838}
839
Erik Språng242e22b2015-05-11 10:17:43 +0200840RTCPSender::BuildResult RTCPSender::BuildReceiverReferenceTime(
841 RtcpContext* ctx) {
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000842
Erik Språng61be2a42015-04-27 13:32:52 +0200843 if (last_xr_rr_.size() >= RTCP_NUMBER_OF_SR)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000844 last_xr_rr_.erase(last_xr_rr_.begin());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000845 last_xr_rr_.insert(std::pair<uint32_t, int64_t>(
Erik Språng242e22b2015-05-11 10:17:43 +0200846 RTCPUtility::MidNtp(ctx->ntp_sec, ctx->ntp_frac),
847 Clock::NtpToMs(ctx->ntp_sec, ctx->ntp_frac)));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000848
Erik Språngca28fdc2015-08-31 14:00:50 +0200849 rtcp::Xr xr;
850 xr.From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000851
Erik Språngca28fdc2015-08-31 14:00:50 +0200852 rtcp::Rrtr rrtr;
853 rrtr.WithNtpSec(ctx->ntp_sec);
854 rrtr.WithNtpFrac(ctx->ntp_frac);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000855
Erik Språngca28fdc2015-08-31 14:00:50 +0200856 xr.WithRrtr(&rrtr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000857
Erik Språngca28fdc2015-08-31 14:00:50 +0200858 // TODO(sprang): Merge XR report sending to contain all of RRTR, DLRR, VOIP?
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000859
Erik Språngca28fdc2015-08-31 14:00:50 +0200860 PacketBuiltCallback callback(ctx);
861 if (!callback.BuildPacket(xr))
862 return BuildResult::kTruncated;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000863
Erik Språng242e22b2015-05-11 10:17:43 +0200864 return BuildResult::kSuccess;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000865}
866
Erik Språng242e22b2015-05-11 10:17:43 +0200867RTCPSender::BuildResult RTCPSender::BuildDlrr(RtcpContext* ctx) {
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::Dlrr dlrr;
Erik Språng242e22b2015-05-11 10:17:43 +0200872 const RtcpReceiveTimeInfo& info = ctx->feedback_state.last_xr_rr;
Erik Språngca28fdc2015-08-31 14:00:50 +0200873 dlrr.WithDlrrItem(info.sourceSSRC, info.lastRR, info.delaySinceLastRR);
874
875 xr.WithDlrr(&dlrr);
876
877 PacketBuiltCallback callback(ctx);
878 if (!callback.BuildPacket(xr))
879 return BuildResult::kTruncated;
Erik Språng242e22b2015-05-11 10:17:43 +0200880
881 return BuildResult::kSuccess;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000882}
883
Erik Språng242e22b2015-05-11 10:17:43 +0200884// TODO(sprang): Add a unit test for this, or remove if the code isn't used.
885RTCPSender::BuildResult RTCPSender::BuildVoIPMetric(RtcpContext* ctx) {
Erik Språngca28fdc2015-08-31 14:00:50 +0200886 rtcp::Xr xr;
887 xr.From(ssrc_);
888
889 rtcp::VoipMetric voip;
890 voip.To(remote_ssrc_);
891 voip.LossRate(xr_voip_metric_.lossRate);
892 voip.DiscardRate(xr_voip_metric_.discardRate);
893 voip.BurstDensity(xr_voip_metric_.burstDensity);
894 voip.GapDensity(xr_voip_metric_.gapDensity);
895 voip.BurstDuration(xr_voip_metric_.burstDuration);
896 voip.GapDuration(xr_voip_metric_.gapDuration);
897 voip.RoundTripDelay(xr_voip_metric_.roundTripDelay);
898 voip.EndSystemDelay(xr_voip_metric_.endSystemDelay);
899 voip.SignalLevel(xr_voip_metric_.signalLevel);
900 voip.NoiseLevel(xr_voip_metric_.noiseLevel);
901 voip.Rerl(xr_voip_metric_.RERL);
902 voip.Gmin(xr_voip_metric_.Gmin);
903 voip.Rfactor(xr_voip_metric_.Rfactor);
904 voip.ExtRfactor(xr_voip_metric_.extRfactor);
905 voip.MosLq(xr_voip_metric_.MOSLQ);
906 voip.MosCq(xr_voip_metric_.MOSCQ);
907 voip.RxConfig(xr_voip_metric_.RXconfig);
908 voip.JbNominal(xr_voip_metric_.JBnominal);
909 voip.JbMax(xr_voip_metric_.JBmax);
910 voip.JbAbsMax(xr_voip_metric_.JBabsMax);
911
912 xr.WithVoipMetric(&voip);
913
914 PacketBuiltCallback callback(ctx);
915 if (!callback.BuildPacket(xr))
Erik Språng242e22b2015-05-11 10:17:43 +0200916 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000917
Erik Språng242e22b2015-05-11 10:17:43 +0200918 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000919}
920
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000921int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200922 RTCPPacketType packetType,
923 int32_t nack_size,
924 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000925 bool repeat,
926 uint64_t pictureID) {
Erik Språng242e22b2015-05-11 10:17:43 +0200927 return SendCompoundRTCP(
928 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
929 nack_size, nack_list, repeat, pictureID);
930}
931
932int32_t RTCPSender::SendCompoundRTCP(
933 const FeedbackState& feedback_state,
934 const std::set<RTCPPacketType>& packetTypes,
935 int32_t nack_size,
936 const uint16_t* nack_list,
937 bool repeat,
938 uint64_t pictureID) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000939 {
Erik Språng242e22b2015-05-11 10:17:43 +0200940 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
pbosda903ea2015-10-02 02:36:56 -0700941 if (method_ == RtcpMode::kOff) {
Erik Språng61be2a42015-04-27 13:32:52 +0200942 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
943 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +0000944 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000945 }
946 uint8_t rtcp_buffer[IP_PACKET_SIZE];
Erik Språng242e22b2015-05-11 10:17:43 +0200947 int rtcp_length =
948 PrepareRTCP(feedback_state, packetTypes, nack_size, nack_list, repeat,
949 pictureID, rtcp_buffer, IP_PACKET_SIZE);
Erik Språng61be2a42015-04-27 13:32:52 +0200950
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000951 // Sanity don't send empty packets.
Erik Språng242e22b2015-05-11 10:17:43 +0200952 if (rtcp_length <= 0)
953 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200954
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000955 return SendToNetwork(rtcp_buffer, static_cast<size_t>(rtcp_length));
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000956}
957
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000958int RTCPSender::PrepareRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200959 const std::set<RTCPPacketType>& packetTypes,
960 int32_t nack_size,
961 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000962 bool repeat,
963 uint64_t pictureID,
964 uint8_t* rtcp_buffer,
965 int buffer_size) {
Erik Språng242e22b2015-05-11 10:17:43 +0200966 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000967
Erik Språng242e22b2015-05-11 10:17:43 +0200968 RtcpContext context(feedback_state, nack_size, nack_list, repeat, pictureID,
969 rtcp_buffer, buffer_size);
970
971 // Add all flags as volatile. Non volatile entries will not be overwritten
972 // and all new volatile flags added will be consumed by the end of this call.
973 SetFlags(packetTypes, true);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000974
Erik Språng61be2a42015-04-27 13:32:52 +0200975 if (packet_type_counter_.first_packet_time_ms == -1)
Erik Språng242e22b2015-05-11 10:17:43 +0200976 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språng61be2a42015-04-27 13:32:52 +0200977
Erik Språng242e22b2015-05-11 10:17:43 +0200978 bool generate_report;
979 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
980 // Report type already explicitly set, don't automatically populate.
981 generate_report = true;
henrikg91d6ede2015-09-17 00:24:34 -0700982 RTC_DCHECK(ConsumeFlag(kRtcpReport) == false);
Erik Språng242e22b2015-05-11 10:17:43 +0200983 } else {
984 generate_report =
pbosda903ea2015-10-02 02:36:56 -0700985 (ConsumeFlag(kRtcpReport) && method_ == RtcpMode::kReducedSize) ||
986 method_ == RtcpMode::kCompound;
Erik Språng242e22b2015-05-11 10:17:43 +0200987 if (generate_report)
988 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000989 }
990
Erik Språng0ea42d32015-06-25 14:46:16 +0200991 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
Erik Språng242e22b2015-05-11 10:17:43 +0200992 SetFlag(kRtcpSdes, true);
993
994 // We need to send our NTP even if we haven't received any reports.
995 clock_->CurrentNtp(context.ntp_sec, context.ntp_frac);
996
997 if (generate_report) {
998 if (!sending_ && xr_send_receiver_reference_time_enabled_)
999 SetFlag(kRtcpXrReceiverReferenceTime, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001000 if (feedback_state.has_last_xr_rr)
Erik Språng242e22b2015-05-11 10:17:43 +02001001 SetFlag(kRtcpXrDlrrReportBlock, true);
1002
1003 // generate next time to send an RTCP report
Erik Språng61be2a42015-04-27 13:32:52 +02001004 // seeded from RTP constructor
1005 int32_t random = rand() % 1000;
1006 int32_t timeToNext = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001007
Erik Språng242e22b2015-05-11 10:17:43 +02001008 if (audio_) {
Erik Språng61be2a42015-04-27 13:32:52 +02001009 timeToNext = (RTCP_INTERVAL_AUDIO_MS / 2) +
1010 (RTCP_INTERVAL_AUDIO_MS * random / 1000);
1011 } else {
1012 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
Erik Språng242e22b2015-05-11 10:17:43 +02001013 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +02001014 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
1015 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
1016 if (send_bitrate_kbit != 0)
1017 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001018 }
Erik Språng61be2a42015-04-27 13:32:52 +02001019 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
1020 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
1021 timeToNext = (minIntervalMs / 2) + (minIntervalMs * random / 1000);
1022 }
Erik Språng242e22b2015-05-11 10:17:43 +02001023 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001024
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001025 StatisticianMap statisticians =
1026 receive_statistics_->GetActiveStatisticians();
1027 if (!statisticians.empty()) {
Erik Språng61be2a42015-04-27 13:32:52 +02001028 for (auto it = statisticians.begin(); it != statisticians.end(); ++it) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001029 RTCPReportBlock report_block;
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001030 if (PrepareReport(feedback_state, it->first, it->second,
1031 &report_block)) {
danilchapdf948f02015-11-13 03:03:13 -08001032 // TODO(danilchap) AddReportBlock may fail (for 2 different reasons).
1033 // Probably it shouldn't be ignored.
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001034 AddReportBlock(report_block);
Erik Språng61be2a42015-04-27 13:32:52 +02001035 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001036 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001037 }
1038 }
1039
Erik Språng242e22b2015-05-11 10:17:43 +02001040 auto it = report_flags_.begin();
1041 while (it != report_flags_.end()) {
1042 auto builder = builders_.find(it->type);
henrikg91d6ede2015-09-17 00:24:34 -07001043 RTC_DCHECK(builder != builders_.end());
Erik Språng242e22b2015-05-11 10:17:43 +02001044 if (it->is_volatile) {
1045 report_flags_.erase(it++);
1046 } else {
1047 ++it;
Erik Språng61be2a42015-04-27 13:32:52 +02001048 }
Erik Språng242e22b2015-05-11 10:17:43 +02001049
1050 uint32_t start_position = context.position;
Erik Språng0ea42d32015-06-25 14:46:16 +02001051 BuildResult result = (this->*(builder->second))(&context);
Erik Språng242e22b2015-05-11 10:17:43 +02001052 switch (result) {
1053 case BuildResult::kError:
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001054 return -1;
Erik Språng242e22b2015-05-11 10:17:43 +02001055 case BuildResult::kTruncated:
1056 return context.position;
1057 case BuildResult::kAborted:
1058 context.position = start_position;
1059 FALLTHROUGH();
1060 case BuildResult::kSuccess:
1061 continue;
Erik Språng61be2a42015-04-27 13:32:52 +02001062 default:
Erik Språng242e22b2015-05-11 10:17:43 +02001063 abort();
Erik Språng61be2a42015-04-27 13:32:52 +02001064 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001065 }
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001066
1067 if (packet_type_counter_observer_ != NULL) {
1068 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
Erik Språng242e22b2015-05-11 10:17:43 +02001069 remote_ssrc_, packet_type_counter_);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001070 }
1071
henrikg91d6ede2015-09-17 00:24:34 -07001072 RTC_DCHECK(AllVolatileFlagsConsumed());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001073
Erik Språng242e22b2015-05-11 10:17:43 +02001074 return context.position;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001075}
1076
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001077bool RTCPSender::PrepareReport(const FeedbackState& feedback_state,
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001078 uint32_t ssrc,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001079 StreamStatistician* statistician,
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001080 RTCPReportBlock* report_block) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001081 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +00001082 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001083 if (!statistician->GetStatistics(&stats, true))
1084 return false;
1085 report_block->fractionLost = stats.fraction_lost;
1086 report_block->cumulativeLost = stats.cumulative_lost;
1087 report_block->extendedHighSeqNum =
1088 stats.extended_max_sequence_number;
1089 report_block->jitter = stats.jitter;
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001090 report_block->remoteSSRC = ssrc;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001091
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001092 // TODO(sprang): Do we really need separate time stamps for each report?
1093 // Get our NTP as late as possible to avoid a race.
1094 uint32_t ntp_secs;
1095 uint32_t ntp_frac;
1096 clock_->CurrentNtp(ntp_secs, ntp_frac);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001097
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001098 // Delay since last received report.
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001099 uint32_t delaySinceLastReceivedSR = 0;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001100 if ((feedback_state.last_rr_ntp_secs != 0) ||
1101 (feedback_state.last_rr_ntp_frac != 0)) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001102 // Get the 16 lowest bits of seconds and the 16 highest bits of fractions.
1103 uint32_t now = ntp_secs & 0x0000FFFF;
Erik Språng61be2a42015-04-27 13:32:52 +02001104 now <<= 16;
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001105 now += (ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001106
Erik Språng61be2a42015-04-27 13:32:52 +02001107 uint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
1108 receiveTime <<= 16;
1109 receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001110
1111 delaySinceLastReceivedSR = now-receiveTime;
1112 }
1113 report_block->delaySinceLastSR = delaySinceLastReceivedSR;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001114 report_block->lastSR = feedback_state.remote_sr;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001115 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +00001116}
1117
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001118int32_t RTCPSender::SendToNetwork(const uint8_t* dataBuffer, size_t length) {
sprang86fd9ed2015-09-29 04:45:43 -07001119 if (transport_->SendRtcp(dataBuffer, length))
1120 return 0;
Erik Språng61be2a42015-04-27 13:32:52 +02001121 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001122}
1123
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001124void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
1125 assert(csrcs.size() <= kRtpCsrcSize);
Erik Språng242e22b2015-05-11 10:17:43 +02001126 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001127 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +00001128}
1129
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001130int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
1131 uint32_t name,
1132 const uint8_t* data,
1133 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +02001134 if (length % 4 != 0) {
1135 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
1136 return -1;
1137 }
Erik Språng242e22b2015-05-11 10:17:43 +02001138 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +00001139
Erik Språng242e22b2015-05-11 10:17:43 +02001140 SetFlag(kRtcpApp, true);
1141 app_sub_type_ = subType;
1142 app_name_ = name;
1143 app_data_.reset(new uint8_t[length]);
1144 app_length_ = length;
1145 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +02001146 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001147}
1148
Erik Språng61be2a42015-04-27 13:32:52 +02001149int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
Erik Språng242e22b2015-05-11 10:17:43 +02001150 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1151 memcpy(&xr_voip_metric_, VoIPMetric, sizeof(RTCPVoIPMetric));
niklase@google.com470e71d2011-07-07 08:21:25 +00001152
Erik Språng242e22b2015-05-11 10:17:43 +02001153 SetFlag(kRtcpXrVoipMetric, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001154 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001155}
1156
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001157void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +02001158 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1159 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001160}
1161
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00001162bool RTCPSender::RtcpXrReceiverReferenceTime() const {
Erik Språng242e22b2015-05-11 10:17:43 +02001163 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1164 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00001165}
1166
niklase@google.com470e71d2011-07-07 08:21:25 +00001167// no callbacks allowed inside this function
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001168int32_t RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
1169 uint32_t maxBitrateKbit) {
Erik Språng242e22b2015-05-11 10:17:43 +02001170 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +00001171
Erik Språng242e22b2015-05-11 10:17:43 +02001172 if (0 == tmmbr_help_.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit)) {
1173 SetFlag(kRtcpTmmbn, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001174 return 0;
1175 }
1176 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001177}
Erik Språng61be2a42015-04-27 13:32:52 +02001178
Erik Språng242e22b2015-05-11 10:17:43 +02001179void RTCPSender::SetFlag(RTCPPacketType type, bool is_volatile) {
1180 report_flags_.insert(ReportFlag(type, is_volatile));
1181}
1182
1183void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
1184 bool is_volatile) {
1185 for (RTCPPacketType type : types)
1186 SetFlag(type, is_volatile);
1187}
1188
1189bool RTCPSender::IsFlagPresent(RTCPPacketType type) const {
1190 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
1191}
1192
1193bool RTCPSender::ConsumeFlag(RTCPPacketType type, bool forced) {
1194 auto it = report_flags_.find(ReportFlag(type, false));
1195 if (it == report_flags_.end())
1196 return false;
1197 if (it->is_volatile || forced)
1198 report_flags_.erase((it));
1199 return true;
1200}
1201
1202bool RTCPSender::AllVolatileFlagsConsumed() const {
1203 for (const ReportFlag& flag : report_flags_) {
1204 if (flag.is_volatile)
1205 return false;
1206 }
1207 return true;
1208}
1209
sprang233bd872015-09-08 13:25:16 -07001210bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
sprang233bd872015-09-08 13:25:16 -07001211 class Sender : public rtcp::RtcpPacket::PacketReadyCallback {
1212 public:
Peter Boströmac547a62015-09-17 23:03:57 +02001213 Sender(Transport* transport)
1214 : transport_(transport), send_failure_(false) {}
sprang233bd872015-09-08 13:25:16 -07001215
1216 void OnPacketReady(uint8_t* data, size_t length) override {
pbos2d566682015-09-28 09:59:31 -07001217 if (!transport_->SendRtcp(data, length))
sprang233bd872015-09-08 13:25:16 -07001218 send_failure_ = true;
1219 }
1220
1221 Transport* const transport_;
sprang233bd872015-09-08 13:25:16 -07001222 bool send_failure_;
sprang86fd9ed2015-09-29 04:45:43 -07001223 } sender(transport_);
sprang233bd872015-09-08 13:25:16 -07001224
1225 uint8_t buffer[IP_PACKET_SIZE];
1226 return packet.BuildExternalBuffer(buffer, IP_PACKET_SIZE, &sender) &&
1227 !sender.send_failure_;
1228}
1229
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001230} // namespace webrtc