blob: ffab90ebe7eb7c5041b57b00d2eb861d03d8dc5e [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"
sprang233bd872015-09-08 13:25:16 -070026#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
tommie4f96502015-10-20 23:00:48 -070027#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010028#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000029
niklase@google.com470e71d2011-07-07 08:21:25 +000030namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000031
32using RTCPUtility::RTCPCnameInformation;
33
Erik Språng61be2a42015-04-27 13:32:52 +020034NACKStringBuilder::NACKStringBuilder()
Erik Språng242e22b2015-05-11 10:17:43 +020035 : stream_(""), count_(0), prevNack_(0), consecutive_(false) {
edjee@google.com79b02892013-04-04 19:43:34 +000036}
37
pbos@webrtc.orgf3e4cee2013-07-31 15:17:19 +000038NACKStringBuilder::~NACKStringBuilder() {}
39
pbos@webrtc.org2f446732013-04-08 11:08:41 +000040void NACKStringBuilder::PushNACK(uint16_t nack)
edjee@google.com79b02892013-04-04 19:43:34 +000041{
Erik Språng242e22b2015-05-11 10:17:43 +020042 if (count_ == 0) {
43 stream_ << nack;
44 } else if (nack == prevNack_ + 1) {
45 consecutive_ = true;
Erik Språng61be2a42015-04-27 13:32:52 +020046 } else {
Erik Språng242e22b2015-05-11 10:17:43 +020047 if (consecutive_) {
48 stream_ << "-" << prevNack_;
49 consecutive_ = false;
edjee@google.com79b02892013-04-04 19:43:34 +000050 }
Erik Språng242e22b2015-05-11 10:17:43 +020051 stream_ << "," << nack;
Erik Språng61be2a42015-04-27 13:32:52 +020052 }
Erik Språng242e22b2015-05-11 10:17:43 +020053 count_++;
54 prevNack_ = nack;
edjee@google.com79b02892013-04-04 19:43:34 +000055}
56
Erik Språng61be2a42015-04-27 13:32:52 +020057std::string NACKStringBuilder::GetResult() {
Erik Språng242e22b2015-05-11 10:17:43 +020058 if (consecutive_) {
59 stream_ << "-" << prevNack_;
60 consecutive_ = false;
Erik Språng61be2a42015-04-27 13:32:52 +020061 }
Erik Språng242e22b2015-05-11 10:17:43 +020062 return stream_.str();
edjee@google.com79b02892013-04-04 19:43:34 +000063}
64
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000065RTCPSender::FeedbackState::FeedbackState()
66 : send_payload_type(0),
67 frequency_hz(0),
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +000068 packets_sent(0),
69 media_bytes_sent(0),
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000070 send_bitrate(0),
71 last_rr_ntp_secs(0),
72 last_rr_ntp_frac(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000073 remote_sr(0),
Erik Språng61be2a42015-04-27 13:32:52 +020074 has_last_xr_rr(false),
75 module(nullptr) {
76}
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000077
Erik Språng242e22b2015-05-11 10:17:43 +020078struct RTCPSender::RtcpContext {
79 RtcpContext(const FeedbackState& feedback_state,
80 int32_t nack_size,
81 const uint16_t* nack_list,
82 bool repeat,
83 uint64_t picture_id,
84 uint8_t* buffer,
85 uint32_t buffer_size)
86 : feedback_state(feedback_state),
87 nack_size(nack_size),
88 nack_list(nack_list),
89 repeat(repeat),
90 picture_id(picture_id),
91 buffer(buffer),
92 buffer_size(buffer_size),
93 ntp_sec(0),
94 ntp_frac(0),
Erik Språng242e22b2015-05-11 10:17:43 +020095 position(0) {}
96
97 uint8_t* AllocateData(uint32_t bytes) {
henrikg91d6ede2015-09-17 00:24:34 -070098 RTC_DCHECK_LE(position + bytes, buffer_size);
Erik Språng242e22b2015-05-11 10:17:43 +020099 uint8_t* ptr = &buffer[position];
100 position += bytes;
101 return ptr;
102 }
103
104 const FeedbackState& feedback_state;
105 int32_t nack_size;
106 const uint16_t* nack_list;
107 bool repeat;
108 uint64_t picture_id;
109 uint8_t* buffer;
110 uint32_t buffer_size;
111 uint32_t ntp_sec;
112 uint32_t ntp_frac;
Erik Språng242e22b2015-05-11 10:17:43 +0200113 uint32_t position;
114};
115
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200116// TODO(sprang): Once all builders use RtcpPacket, call SendToNetwork() here.
117class RTCPSender::PacketBuiltCallback
118 : public rtcp::RtcpPacket::PacketReadyCallback {
119 public:
120 PacketBuiltCallback(RtcpContext* context) : context_(context) {}
121 virtual ~PacketBuiltCallback() {}
122 void OnPacketReady(uint8_t* data, size_t length) override {
123 context_->position += length;
124 }
Erik Språng72aa9a62015-07-31 16:16:02 +0200125 bool BuildPacket(const rtcp::RtcpPacket& packet) {
126 return packet.BuildExternalBuffer(
127 &context_->buffer[context_->position],
128 context_->buffer_size - context_->position, this);
129 }
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200130
131 private:
132 RtcpContext* const context_;
133};
134
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000135RTCPSender::RTCPSender(
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000136 bool audio,
137 Clock* clock,
138 ReceiveStatistics* receive_statistics,
sprang86fd9ed2015-09-29 04:45:43 -0700139 RtcpPacketTypeCounterObserver* packet_type_counter_observer,
140 Transport* outgoing_transport)
Peter Boströmac547a62015-09-17 23:03:57 +0200141 : audio_(audio),
Erik Språng242e22b2015-05-11 10:17:43 +0200142 clock_(clock),
pbosda903ea2015-10-02 02:36:56 -0700143 method_(RtcpMode::kOff),
sprang86fd9ed2015-09-29 04:45:43 -0700144 transport_(outgoing_transport),
niklase@google.com470e71d2011-07-07 08:21:25 +0000145
Erik Språng242e22b2015-05-11 10:17:43 +0200146 critical_section_rtcp_sender_(
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000147 CriticalSectionWrapper::CreateCriticalSection()),
Erik Språng242e22b2015-05-11 10:17:43 +0200148 using_nack_(false),
149 sending_(false),
150 remb_enabled_(false),
Erik Språng242e22b2015-05-11 10:17:43 +0200151 next_time_to_send_rtcp_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000152 start_timestamp_(0),
153 last_rtp_timestamp_(0),
154 last_frame_capture_time_ms_(-1),
Erik Språng242e22b2015-05-11 10:17:43 +0200155 ssrc_(0),
156 remote_ssrc_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000157 receive_statistics_(receive_statistics),
niklase@google.com470e71d2011-07-07 08:21:25 +0000158
Erik Språng242e22b2015-05-11 10:17:43 +0200159 sequence_number_fir_(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000160
Erik Språng242e22b2015-05-11 10:17:43 +0200161 remb_bitrate_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000162
Erik Språng242e22b2015-05-11 10:17:43 +0200163 tmmbr_help_(),
164 tmmbr_send_(0),
165 packet_oh_send_(0),
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000166
Erik Språng242e22b2015-05-11 10:17:43 +0200167 app_sub_type_(0),
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200168 app_name_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200169 app_data_(nullptr),
170 app_length_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000171
Erik Språng242e22b2015-05-11 10:17:43 +0200172 xr_send_receiver_reference_time_enabled_(false),
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000173 packet_type_counter_observer_(packet_type_counter_observer) {
Erik Språng242e22b2015-05-11 10:17:43 +0200174 memset(last_send_report_, 0, sizeof(last_send_report_));
175 memset(last_rtcp_time_, 0, sizeof(last_rtcp_time_));
sprang86fd9ed2015-09-29 04:45:43 -0700176 RTC_DCHECK(transport_ != nullptr);
Erik Språng242e22b2015-05-11 10:17:43 +0200177
178 builders_[kRtcpSr] = &RTCPSender::BuildSR;
179 builders_[kRtcpRr] = &RTCPSender::BuildRR;
Erik Språng0ea42d32015-06-25 14:46:16 +0200180 builders_[kRtcpSdes] = &RTCPSender::BuildSDES;
Erik Språng242e22b2015-05-11 10:17:43 +0200181 builders_[kRtcpPli] = &RTCPSender::BuildPLI;
182 builders_[kRtcpFir] = &RTCPSender::BuildFIR;
183 builders_[kRtcpSli] = &RTCPSender::BuildSLI;
184 builders_[kRtcpRpsi] = &RTCPSender::BuildRPSI;
185 builders_[kRtcpRemb] = &RTCPSender::BuildREMB;
186 builders_[kRtcpBye] = &RTCPSender::BuildBYE;
187 builders_[kRtcpApp] = &RTCPSender::BuildAPP;
188 builders_[kRtcpTmmbr] = &RTCPSender::BuildTMMBR;
189 builders_[kRtcpTmmbn] = &RTCPSender::BuildTMMBN;
190 builders_[kRtcpNack] = &RTCPSender::BuildNACK;
191 builders_[kRtcpXrVoipMetric] = &RTCPSender::BuildVoIPMetric;
192 builders_[kRtcpXrReceiverReferenceTime] =
193 &RTCPSender::BuildReceiverReferenceTime;
194 builders_[kRtcpXrDlrrReportBlock] = &RTCPSender::BuildDlrr;
niklase@google.com470e71d2011-07-07 08:21:25 +0000195}
196
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000197RTCPSender::~RTCPSender() {
niklase@google.com470e71d2011-07-07 08:21:25 +0000198}
199
pbosda903ea2015-10-02 02:36:56 -0700200RtcpMode RTCPSender::Status() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200201 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
202 return method_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000203}
204
pbosda903ea2015-10-02 02:36:56 -0700205void RTCPSender::SetRTCPStatus(RtcpMode method) {
Erik Språng242e22b2015-05-11 10:17:43 +0200206 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
207 method_ = method;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000208
pbosda903ea2015-10-02 02:36:56 -0700209 if (method == RtcpMode::kOff)
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000210 return;
Erik Språng242e22b2015-05-11 10:17:43 +0200211 next_time_to_send_rtcp_ =
212 clock_->TimeInMilliseconds() +
213 (audio_ ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000214}
215
Erik Språng61be2a42015-04-27 13:32:52 +0200216bool RTCPSender::Sending() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200217 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
218 return sending_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000219}
220
Erik Språng61be2a42015-04-27 13:32:52 +0200221int32_t RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
222 bool sending) {
223 bool sendRTCPBye = false;
224 {
Erik Språng242e22b2015-05-11 10:17:43 +0200225 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000226
pbosda903ea2015-10-02 02:36:56 -0700227 if (method_ != RtcpMode::kOff) {
Erik Språng242e22b2015-05-11 10:17:43 +0200228 if (sending == false && sending_ == true) {
Erik Språng61be2a42015-04-27 13:32:52 +0200229 // Trigger RTCP bye
230 sendRTCPBye = true;
231 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000232 }
Erik Språng242e22b2015-05-11 10:17:43 +0200233 sending_ = sending;
Erik Språng61be2a42015-04-27 13:32:52 +0200234 }
235 if (sendRTCPBye)
236 return SendRTCP(feedback_state, kRtcpBye);
237 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000238}
239
Erik Språng61be2a42015-04-27 13:32:52 +0200240bool RTCPSender::REMB() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200241 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
242 return remb_enabled_;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000243}
244
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000245void RTCPSender::SetREMBStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200246 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
247 remb_enabled_ = enable;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000248}
249
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000250void RTCPSender::SetREMBData(uint32_t bitrate,
251 const std::vector<uint32_t>& ssrcs) {
Erik Språng242e22b2015-05-11 10:17:43 +0200252 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
253 remb_bitrate_ = bitrate;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000254 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000255
Erik Språng242e22b2015-05-11 10:17:43 +0200256 if (remb_enabled_)
257 SetFlag(kRtcpRemb, false);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000258 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
259 // throttled by the caller.
Erik Språng242e22b2015-05-11 10:17:43 +0200260 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000261}
262
Erik Språng61be2a42015-04-27 13:32:52 +0200263bool RTCPSender::TMMBR() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200264 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
265 return IsFlagPresent(RTCPPacketType::kRtcpTmmbr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000266}
267
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000268void RTCPSender::SetTMMBRStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200269 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
270 if (enable) {
271 SetFlag(RTCPPacketType::kRtcpTmmbr, false);
272 } else {
273 ConsumeFlag(RTCPPacketType::kRtcpTmmbr, true);
274 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000275}
276
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000277void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
Erik Språng242e22b2015-05-11 10:17:43 +0200278 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000279 start_timestamp_ = start_timestamp;
280}
281
282void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
283 int64_t capture_time_ms) {
Erik Språng242e22b2015-05-11 10:17:43 +0200284 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000285 last_rtp_timestamp_ = rtp_timestamp;
286 if (capture_time_ms < 0) {
287 // We don't currently get a capture time from VoiceEngine.
Erik Språng242e22b2015-05-11 10:17:43 +0200288 last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000289 } else {
290 last_frame_capture_time_ms_ = capture_time_ms;
291 }
292}
293
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000294void RTCPSender::SetSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200295 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000296
Erik Språng242e22b2015-05-11 10:17:43 +0200297 if (ssrc_ != 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200298 // not first SetSSRC, probably due to a collision
299 // schedule a new RTCP report
300 // make sure that we send a RTP packet
Erik Språng242e22b2015-05-11 10:17:43 +0200301 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
Erik Språng61be2a42015-04-27 13:32:52 +0200302 }
Erik Språng242e22b2015-05-11 10:17:43 +0200303 ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000304}
305
Erik Språng61be2a42015-04-27 13:32:52 +0200306void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200307 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
308 remote_ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000309}
310
Peter Boström9ba52f82015-06-01 14:12:28 +0200311int32_t RTCPSender::SetCNAME(const char* c_name) {
312 if (!c_name)
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000313 return -1;
314
henrikg91d6ede2015-09-17 00:24:34 -0700315 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
Erik Språng242e22b2015-05-11 10:17:43 +0200316 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200317 cname_ = c_name;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000318 return 0;
319}
320
Erik Språng0ea42d32015-06-25 14:46:16 +0200321int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC, const char* c_name) {
322 assert(c_name);
henrikg91d6ede2015-09-17 00:24:34 -0700323 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
Erik Språng242e22b2015-05-11 10:17:43 +0200324 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200325 if (csrc_cnames_.size() >= kRtpCsrcSize)
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000326 return -1;
Erik Språng0ea42d32015-06-25 14:46:16 +0200327
328 csrc_cnames_[SSRC] = c_name;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000329 return 0;
330}
331
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000332int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
Erik Språng242e22b2015-05-11 10:17:43 +0200333 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200334 auto it = csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000335
Erik Språng242e22b2015-05-11 10:17:43 +0200336 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000337 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200338
Erik Språng242e22b2015-05-11 10:17:43 +0200339 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000340 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000341}
342
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000343bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
niklase@google.com470e71d2011-07-07 08:21:25 +0000344/*
345 For audio we use a fix 5 sec interval
346
347 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000348 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
349 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000350
351
352From RFC 3550
353
354 MAX RTCP BW is 5% if the session BW
355 A send report is approximately 65 bytes inc CNAME
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000356 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000357
358 The RECOMMENDED value for the reduced minimum in seconds is 360
359 divided by the session bandwidth in kilobits/second. This minimum
360 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
361
362 If the participant has not yet sent an RTCP packet (the variable
363 initial is true), the constant Tmin is set to 2.5 seconds, else it
364 is set to 5 seconds.
365
366 The interval between RTCP packets is varied randomly over the
367 range [0.5,1.5] times the calculated interval to avoid unintended
368 synchronization of all participants
369
370 if we send
371 If the participant is a sender (we_sent true), the constant C is
372 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
373 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
374 number of senders.
375
376 if we receive only
377 If we_sent is not true, the constant C is set
378 to the average RTCP packet size divided by 75% of the RTCP
379 bandwidth. The constant n is set to the number of receivers
380 (members - senders). If the number of senders is greater than
381 25%, senders and receivers are treated together.
382
383 reconsideration NOT required for peer-to-peer
384 "timer reconsideration" is
385 employed. This algorithm implements a simple back-off mechanism
386 which causes users to hold back RTCP packet transmission if the
387 group sizes are increasing.
388
389 n = number of members
390 C = avg_size/(rtcpBW/4)
391
392 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
393
394 4. The calculated interval T is set to a number uniformly distributed
395 between 0.5 and 1.5 times the deterministic calculated interval.
396
397 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
398 for the fact that the timer reconsideration algorithm converges to
399 a value of the RTCP bandwidth below the intended average
400*/
401
Erik Språng242e22b2015-05-11 10:17:43 +0200402 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000403
Erik Språng242e22b2015-05-11 10:17:43 +0200404 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
xians@webrtc.org8738d272011-11-25 13:43:53 +0000405
pbosda903ea2015-10-02 02:36:56 -0700406 if (method_ == RtcpMode::kOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000407 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000408
Erik Språng242e22b2015-05-11 10:17:43 +0200409 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200410 // for video key-frames we want to send the RTCP before the large key-frame
411 // if we have a 100 ms margin
412 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
413 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000414
Erik Språng242e22b2015-05-11 10:17:43 +0200415 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200416 return true;
417 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200418 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200419 // wrap
420 return true;
421 }
422 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000423}
424
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000425int64_t RTCPSender::SendTimeOfSendReport(uint32_t sendReport) {
Erik Språng242e22b2015-05-11 10:17:43 +0200426 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000427
Erik Språng61be2a42015-04-27 13:32:52 +0200428 // This is only saved when we are the sender
Erik Språng242e22b2015-05-11 10:17:43 +0200429 if ((last_send_report_[0] == 0) || (sendReport == 0)) {
Erik Språng61be2a42015-04-27 13:32:52 +0200430 return 0; // will be ignored
431 } else {
432 for (int i = 0; i < RTCP_NUMBER_OF_SR; ++i) {
Erik Språng242e22b2015-05-11 10:17:43 +0200433 if (last_send_report_[i] == sendReport)
434 return last_rtcp_time_[i];
niklase@google.com470e71d2011-07-07 08:21:25 +0000435 }
Erik Språng61be2a42015-04-27 13:32:52 +0200436 }
437 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000438}
439
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000440bool RTCPSender::SendTimeOfXrRrReport(uint32_t mid_ntp,
441 int64_t* time_ms) const {
Erik Språng242e22b2015-05-11 10:17:43 +0200442 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000443
444 if (last_xr_rr_.empty()) {
445 return false;
446 }
447 std::map<uint32_t, int64_t>::const_iterator it = last_xr_rr_.find(mid_ntp);
448 if (it == last_xr_rr_.end()) {
449 return false;
450 }
451 *time_ms = it->second;
452 return true;
453}
454
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200455int32_t RTCPSender::AddReportBlock(const RTCPReportBlock& report_block) {
456 if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000457 LOG(LS_WARNING) << "Too many report blocks.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000458 return -1;
459 }
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200460 rtcp::ReportBlock* block = &report_blocks_[report_block.remoteSSRC];
461 block->To(report_block.remoteSSRC);
462 block->WithFractionLost(report_block.fractionLost);
danilchapdf948f02015-11-13 03:03:13 -0800463 if (!block->WithCumulativeLost(report_block.cumulativeLost)) {
464 LOG(LS_WARNING) << "Cumulative lost is oversized.";
465 return -1;
466 }
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200467 block->WithExtHighestSeqNum(report_block.extendedHighSeqNum);
468 block->WithJitter(report_block.jitter);
469 block->WithLastSr(report_block.lastSR);
470 block->WithDelayLastSr(report_block.delaySinceLastSR);
471
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000472 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000473}
474
Erik Språng242e22b2015-05-11 10:17:43 +0200475RTCPSender::BuildResult RTCPSender::BuildSR(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200476 for (int i = (RTCP_NUMBER_OF_SR - 2); i >= 0; i--) {
477 // shift old
Erik Språng242e22b2015-05-11 10:17:43 +0200478 last_send_report_[i + 1] = last_send_report_[i];
479 last_rtcp_time_[i + 1] = last_rtcp_time_[i];
Erik Språng61be2a42015-04-27 13:32:52 +0200480 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000481
Erik Språng242e22b2015-05-11 10:17:43 +0200482 last_rtcp_time_[0] = Clock::NtpToMs(ctx->ntp_sec, ctx->ntp_frac);
483 last_send_report_[0] = (ctx->ntp_sec << 16) + (ctx->ntp_frac >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000484
Erik Språng61be2a42015-04-27 13:32:52 +0200485 // The timestamp of this RTCP packet should be estimated as the timestamp of
486 // the frame being captured at this moment. We are calculating that
487 // timestamp as the last frame's timestamp + the time since the last frame
488 // was captured.
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200489 uint32_t rtp_timestamp =
490 start_timestamp_ + last_rtp_timestamp_ +
491 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) *
492 (ctx->feedback_state.frequency_hz / 1000);
niklase@google.com470e71d2011-07-07 08:21:25 +0000493
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200494 rtcp::SenderReport report;
495 report.From(ssrc_);
496 report.WithNtpSec(ctx->ntp_sec);
497 report.WithNtpFrac(ctx->ntp_frac);
498 report.WithRtpTimestamp(rtp_timestamp);
499 report.WithPacketCount(ctx->feedback_state.packets_sent);
500 report.WithOctetCount(ctx->feedback_state.media_bytes_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000501
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200502 for (auto it : report_blocks_)
503 report.WithReportBlock(it.second);
niklase@google.com470e71d2011-07-07 08:21:25 +0000504
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200505 PacketBuiltCallback callback(ctx);
Erik Språng72aa9a62015-07-31 16:16:02 +0200506 if (!callback.BuildPacket(report))
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200507 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000508
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200509 report_blocks_.clear();
Erik Språng242e22b2015-05-11 10:17:43 +0200510 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000511}
512
Erik Språng0ea42d32015-06-25 14:46:16 +0200513RTCPSender::BuildResult RTCPSender::BuildSDES(RtcpContext* ctx) {
514 size_t length_cname = cname_.length();
henrikg91d6ede2015-09-17 00:24:34 -0700515 RTC_CHECK_LT(length_cname, static_cast<size_t>(RTCP_CNAME_SIZE));
niklase@google.com470e71d2011-07-07 08:21:25 +0000516
Erik Språng0ea42d32015-06-25 14:46:16 +0200517 rtcp::Sdes sdes;
518 sdes.WithCName(ssrc_, cname_);
519
520 for (const auto it : csrc_cnames_)
521 sdes.WithCName(it.first, it.second);
522
523 PacketBuiltCallback callback(ctx);
Erik Språng72aa9a62015-07-31 16:16:02 +0200524 if (!callback.BuildPacket(sdes))
Erik Språng242e22b2015-05-11 10:17:43 +0200525 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000526
Erik Språng242e22b2015-05-11 10:17:43 +0200527 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000528}
529
Erik Språng242e22b2015-05-11 10:17:43 +0200530RTCPSender::BuildResult RTCPSender::BuildRR(RtcpContext* ctx) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200531 rtcp::ReceiverReport report;
532 report.From(ssrc_);
533 for (auto it : report_blocks_)
534 report.WithReportBlock(it.second);
535
536 PacketBuiltCallback callback(ctx);
Erik Språng72aa9a62015-07-31 16:16:02 +0200537 if (!callback.BuildPacket(report))
Erik Språng242e22b2015-05-11 10:17:43 +0200538 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200539
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200540 report_blocks_.clear();
Erik Språng242e22b2015-05-11 10:17:43 +0200541
542 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000543}
544
Erik Språng242e22b2015-05-11 10:17:43 +0200545RTCPSender::BuildResult RTCPSender::BuildPLI(RtcpContext* ctx) {
Erik Språng72aa9a62015-07-31 16:16:02 +0200546 rtcp::Pli pli;
547 pli.From(ssrc_);
548 pli.To(remote_ssrc_);
549
550 PacketBuiltCallback callback(ctx);
551 if (!callback.BuildPacket(pli))
Erik Språng242e22b2015-05-11 10:17:43 +0200552 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200553
Erik Språng242e22b2015-05-11 10:17:43 +0200554 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
555 "RTCPSender::PLI");
556 ++packet_type_counter_.pli_packets;
557 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
558 ssrc_, packet_type_counter_.pli_packets);
559
560 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +0200561}
562
Erik Språng242e22b2015-05-11 10:17:43 +0200563RTCPSender::BuildResult RTCPSender::BuildFIR(RtcpContext* ctx) {
Erik Språng242e22b2015-05-11 10:17:43 +0200564 if (!ctx->repeat)
sprang62dae192015-08-05 02:35:35 -0700565 ++sequence_number_fir_; // Do not increase if repetition.
niklase@google.com470e71d2011-07-07 08:21:25 +0000566
sprang62dae192015-08-05 02:35:35 -0700567 rtcp::Fir fir;
568 fir.From(ssrc_);
569 fir.To(remote_ssrc_);
570 fir.WithCommandSeqNum(sequence_number_fir_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000571
sprang62dae192015-08-05 02:35:35 -0700572 PacketBuiltCallback callback(ctx);
573 if (!callback.BuildPacket(fir))
574 return BuildResult::kTruncated;
Erik Språng242e22b2015-05-11 10:17:43 +0200575
576 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
577 "RTCPSender::FIR");
578 ++packet_type_counter_.fir_packets;
579 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
580 ssrc_, packet_type_counter_.fir_packets);
581
582 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000583}
584
585/*
586 0 1 2 3
587 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
588 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
589 | First | Number | PictureID |
590 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
591*/
Erik Språng242e22b2015-05-11 10:17:43 +0200592RTCPSender::BuildResult RTCPSender::BuildSLI(RtcpContext* ctx) {
sprang0365a272015-08-11 01:02:37 -0700593 rtcp::Sli sli;
594 sli.From(ssrc_);
595 sli.To(remote_ssrc_);
596 // Crop picture id to 6 least significant bits.
597 sli.WithPictureId(ctx->picture_id & 0x3F);
598 sli.WithFirstMb(0);
599 sli.WithNumberOfMb(0x1FFF); // 13 bits, only ones for now.
600
601 PacketBuiltCallback callback(ctx);
602 if (!callback.BuildPacket(sli))
Erik Språng242e22b2015-05-11 10:17:43 +0200603 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000604
Erik Språng242e22b2015-05-11 10:17:43 +0200605 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000606}
607
608/*
609 0 1 2 3
610 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
611 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
612 | PB |0| Payload Type| Native RPSI bit string |
613 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
614 | defined per codec ... | Padding (0) |
615 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
616*/
617/*
618* Note: not generic made for VP8
619*/
Erik Språng242e22b2015-05-11 10:17:43 +0200620RTCPSender::BuildResult RTCPSender::BuildRPSI(RtcpContext* ctx) {
621 if (ctx->feedback_state.send_payload_type == 0xFF)
622 return BuildResult::kError;
623
sprangcf7f54d2015-08-13 04:37:42 -0700624 rtcp::Rpsi rpsi;
625 rpsi.From(ssrc_);
626 rpsi.To(remote_ssrc_);
627 rpsi.WithPayloadType(ctx->feedback_state.send_payload_type);
628 rpsi.WithPictureId(ctx->picture_id);
629
630 PacketBuiltCallback callback(ctx);
631 if (!callback.BuildPacket(rpsi))
Erik Språng242e22b2015-05-11 10:17:43 +0200632 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000633
Erik Språng242e22b2015-05-11 10:17:43 +0200634 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000635}
636
Erik Språng242e22b2015-05-11 10:17:43 +0200637RTCPSender::BuildResult RTCPSender::BuildREMB(RtcpContext* ctx) {
sprangdd4edc52015-08-21 04:21:51 -0700638 rtcp::Remb remb;
639 remb.From(ssrc_);
640 for (uint32_t ssrc : remb_ssrcs_)
641 remb.AppliesTo(ssrc);
642 remb.WithBitrateBps(remb_bitrate_);
643
644 PacketBuiltCallback callback(ctx);
645 if (!callback.BuildPacket(remb))
Erik Språng242e22b2015-05-11 10:17:43 +0200646 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200647
Erik Språng242e22b2015-05-11 10:17:43 +0200648 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
649 "RTCPSender::REMB");
650
651 return BuildResult::kSuccess;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000652}
653
Erik Språng61be2a42015-04-27 13:32:52 +0200654void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
Erik Språng242e22b2015-05-11 10:17:43 +0200655 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
656 tmmbr_send_ = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000657}
658
Erik Språng242e22b2015-05-11 10:17:43 +0200659RTCPSender::BuildResult RTCPSender::BuildTMMBR(RtcpContext* ctx) {
660 if (ctx->feedback_state.module == NULL)
661 return BuildResult::kError;
Erik Språng61be2a42015-04-27 13:32:52 +0200662 // Before sending the TMMBR check the received TMMBN, only an owner is
663 // allowed to raise the bitrate:
664 // * If the sender is an owner of the TMMBN -> send TMMBR
665 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000666
Erik Språng61be2a42015-04-27 13:32:52 +0200667 // get current bounding set from RTCP receiver
668 bool tmmbrOwner = false;
669 // store in candidateSet, allocates one extra slot
Erik Språng242e22b2015-05-11 10:17:43 +0200670 TMMBRSet* candidateSet = tmmbr_help_.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000671
Erik Språng242e22b2015-05-11 10:17:43 +0200672 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
673 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
Erik Språng61be2a42015-04-27 13:32:52 +0200674 // since RTCPreceiver is not doing the reverse we should be fine
675 int32_t lengthOfBoundingSet =
Erik Språng242e22b2015-05-11 10:17:43 +0200676 ctx->feedback_state.module->BoundingSet(tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +0000677
Erik Språng61be2a42015-04-27 13:32:52 +0200678 if (lengthOfBoundingSet > 0) {
679 for (int32_t i = 0; i < lengthOfBoundingSet; i++) {
Erik Språng242e22b2015-05-11 10:17:43 +0200680 if (candidateSet->Tmmbr(i) == tmmbr_send_ &&
681 candidateSet->PacketOH(i) == packet_oh_send_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200682 // do not send the same tuple
Erik Språng242e22b2015-05-11 10:17:43 +0200683 return BuildResult::kAborted;
Erik Språng61be2a42015-04-27 13:32:52 +0200684 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000685 }
Erik Språng61be2a42015-04-27 13:32:52 +0200686 if (!tmmbrOwner) {
687 // use received bounding set as candidate set
688 // add current tuple
Erik Språng242e22b2015-05-11 10:17:43 +0200689 candidateSet->SetEntry(lengthOfBoundingSet, tmmbr_send_, packet_oh_send_,
690 ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200691 int numCandidates = lengthOfBoundingSet + 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000692
Erik Språng61be2a42015-04-27 13:32:52 +0200693 // find bounding set
694 TMMBRSet* boundingSet = NULL;
Erik Språng242e22b2015-05-11 10:17:43 +0200695 int numBoundingSet = tmmbr_help_.FindTMMBRBoundingSet(boundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200696 if (numBoundingSet > 0 || numBoundingSet <= numCandidates)
Erik Språng242e22b2015-05-11 10:17:43 +0200697 tmmbrOwner = tmmbr_help_.IsOwner(ssrc_, numBoundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200698 if (!tmmbrOwner) {
699 // did not enter bounding set, no meaning to send this request
Erik Språng242e22b2015-05-11 10:17:43 +0200700 return BuildResult::kAborted;
Erik Språng61be2a42015-04-27 13:32:52 +0200701 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000702 }
Erik Språng61be2a42015-04-27 13:32:52 +0200703 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000704
Erik Språng242e22b2015-05-11 10:17:43 +0200705 if (tmmbr_send_) {
sprang81a3e602015-08-21 05:30:11 -0700706 rtcp::Tmmbr tmmbr;
707 tmmbr.From(ssrc_);
708 tmmbr.To(remote_ssrc_);
709 tmmbr.WithBitrateKbps(tmmbr_send_);
710 tmmbr.WithOverhead(packet_oh_send_);
711
712 PacketBuiltCallback callback(ctx);
713 if (!callback.BuildPacket(tmmbr))
Erik Språng242e22b2015-05-11 10:17:43 +0200714 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200715 }
Erik Språng242e22b2015-05-11 10:17:43 +0200716 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +0200717}
718
Erik Språng242e22b2015-05-11 10:17:43 +0200719RTCPSender::BuildResult RTCPSender::BuildTMMBN(RtcpContext* ctx) {
720 TMMBRSet* boundingSet = tmmbr_help_.BoundingSetToSend();
Erik Språng61be2a42015-04-27 13:32:52 +0200721 if (boundingSet == NULL)
Erik Språng242e22b2015-05-11 10:17:43 +0200722 return BuildResult::kError;
Erik Språng61be2a42015-04-27 13:32:52 +0200723
sprangd83df502015-08-27 01:05:08 -0700724 rtcp::Tmmbn tmmbn;
725 tmmbn.From(ssrc_);
726 for (uint32_t i = 0; i < boundingSet->lengthOfSet(); i++) {
727 if (boundingSet->Tmmbr(i) > 0) {
728 tmmbn.WithTmmbr(boundingSet->Ssrc(i), boundingSet->Tmmbr(i),
729 boundingSet->PacketOH(i));
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000730 }
Erik Språng61be2a42015-04-27 13:32:52 +0200731 }
sprangd83df502015-08-27 01:05:08 -0700732
733 PacketBuiltCallback callback(ctx);
734 if (!callback.BuildPacket(tmmbn))
735 return BuildResult::kTruncated;
Erik Språng242e22b2015-05-11 10:17:43 +0200736
737 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000738}
739
Erik Språng242e22b2015-05-11 10:17:43 +0200740RTCPSender::BuildResult RTCPSender::BuildAPP(RtcpContext* ctx) {
Erik Språng521875a2015-09-01 10:11:16 +0200741 rtcp::App app;
742 app.From(ssrc_);
743 app.WithSubType(app_sub_type_);
744 app.WithName(app_name_);
745 app.WithData(app_data_.get(), app_length_);
746
747 PacketBuiltCallback callback(ctx);
748 if (!callback.BuildPacket(app))
Erik Språng242e22b2015-05-11 10:17:43 +0200749 return BuildResult::kTruncated;
Erik Språng242e22b2015-05-11 10:17:43 +0200750
751 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +0200752}
753
Erik Språng242e22b2015-05-11 10:17:43 +0200754RTCPSender::BuildResult RTCPSender::BuildNACK(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200755 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200756 if (ctx->position + 16 >= IP_PACKET_SIZE) {
Erik Språng61be2a42015-04-27 13:32:52 +0200757 LOG(LS_WARNING) << "Failed to build NACK.";
Erik Språng242e22b2015-05-11 10:17:43 +0200758 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200759 }
760
Erik Språng242e22b2015-05-11 10:17:43 +0200761 // int size, uint16_t* nack_list
Erik Språng61be2a42015-04-27 13:32:52 +0200762 // add nack list
763 uint8_t FMT = 1;
Erik Språng242e22b2015-05-11 10:17:43 +0200764 *ctx->AllocateData(1) = 0x80 + FMT;
765 *ctx->AllocateData(1) = 205;
Erik Språng61be2a42015-04-27 13:32:52 +0200766
Erik Språng242e22b2015-05-11 10:17:43 +0200767 *ctx->AllocateData(1) = 0;
768 int nack_size_pos_ = ctx->position;
769 *ctx->AllocateData(1) = 3; // setting it to one kNACK signal as default
Erik Språng61be2a42015-04-27 13:32:52 +0200770
771 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200772 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200773
774 // Add the remote SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200775 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200776
777 // Build NACK bitmasks and write them to the RTCP message.
778 // The nack list should be sorted and not contain duplicates if one
779 // wants to build the smallest rtcp nack packet.
780 int numOfNackFields = 0;
781 int maxNackFields =
Erik Språng242e22b2015-05-11 10:17:43 +0200782 std::min<int>(kRtcpMaxNackFields, (IP_PACKET_SIZE - ctx->position) / 4);
Erik Språng61be2a42015-04-27 13:32:52 +0200783 int i = 0;
Erik Språng242e22b2015-05-11 10:17:43 +0200784 while (i < ctx->nack_size && numOfNackFields < maxNackFields) {
785 uint16_t nack = ctx->nack_list[i++];
Erik Språng61be2a42015-04-27 13:32:52 +0200786 uint16_t bitmask = 0;
Erik Språng242e22b2015-05-11 10:17:43 +0200787 while (i < ctx->nack_size) {
788 int shift = static_cast<uint16_t>(ctx->nack_list[i] - nack) - 1;
Erik Språng61be2a42015-04-27 13:32:52 +0200789 if (shift >= 0 && shift <= 15) {
790 bitmask |= (1 << shift);
791 ++i;
792 } else {
793 break;
794 }
795 }
796 // Write the sequence number and the bitmask to the packet.
Erik Språng242e22b2015-05-11 10:17:43 +0200797 assert(ctx->position + 4 < IP_PACKET_SIZE);
798 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2), nack);
799 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2), bitmask);
Erik Språng61be2a42015-04-27 13:32:52 +0200800 numOfNackFields++;
801 }
Erik Språng242e22b2015-05-11 10:17:43 +0200802 ctx->buffer[nack_size_pos_] = static_cast<uint8_t>(2 + numOfNackFields);
Erik Språng61be2a42015-04-27 13:32:52 +0200803
Erik Språng242e22b2015-05-11 10:17:43 +0200804 if (i != ctx->nack_size)
Erik Språng61be2a42015-04-27 13:32:52 +0200805 LOG(LS_WARNING) << "Nack list too large for one packet.";
806
807 // Report stats.
808 NACKStringBuilder stringBuilder;
809 for (int idx = 0; idx < i; ++idx) {
Erik Språng242e22b2015-05-11 10:17:43 +0200810 stringBuilder.PushNACK(ctx->nack_list[idx]);
811 nack_stats_.ReportRequest(ctx->nack_list[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +0200812 }
Erik Språng61be2a42015-04-27 13:32:52 +0200813 packet_type_counter_.nack_requests = nack_stats_.requests();
814 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +0200815
816 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
817 "RTCPSender::NACK", "nacks",
818 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
819 ++packet_type_counter_.nack_packets;
820 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
821 ssrc_, packet_type_counter_.nack_packets);
822
823 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +0200824}
825
Erik Språng242e22b2015-05-11 10:17:43 +0200826RTCPSender::BuildResult RTCPSender::BuildBYE(RtcpContext* ctx) {
sprangd8ee4f92015-08-24 03:25:19 -0700827 rtcp::Bye bye;
828 bye.From(ssrc_);
829 for (uint32_t csrc : csrcs_)
830 bye.WithCsrc(csrc);
831
832 PacketBuiltCallback callback(ctx);
833 if (!callback.BuildPacket(bye))
Erik Språng242e22b2015-05-11 10:17:43 +0200834 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000835
Erik Språng242e22b2015-05-11 10:17:43 +0200836 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000837}
838
Erik Språng242e22b2015-05-11 10:17:43 +0200839RTCPSender::BuildResult RTCPSender::BuildReceiverReferenceTime(
840 RtcpContext* ctx) {
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000841
Erik Språng61be2a42015-04-27 13:32:52 +0200842 if (last_xr_rr_.size() >= RTCP_NUMBER_OF_SR)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000843 last_xr_rr_.erase(last_xr_rr_.begin());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000844 last_xr_rr_.insert(std::pair<uint32_t, int64_t>(
Erik Språng242e22b2015-05-11 10:17:43 +0200845 RTCPUtility::MidNtp(ctx->ntp_sec, ctx->ntp_frac),
846 Clock::NtpToMs(ctx->ntp_sec, ctx->ntp_frac)));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000847
Erik Språngca28fdc2015-08-31 14:00:50 +0200848 rtcp::Xr xr;
849 xr.From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000850
Erik Språngca28fdc2015-08-31 14:00:50 +0200851 rtcp::Rrtr rrtr;
852 rrtr.WithNtpSec(ctx->ntp_sec);
853 rrtr.WithNtpFrac(ctx->ntp_frac);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000854
Erik Språngca28fdc2015-08-31 14:00:50 +0200855 xr.WithRrtr(&rrtr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000856
Erik Språngca28fdc2015-08-31 14:00:50 +0200857 // TODO(sprang): Merge XR report sending to contain all of RRTR, DLRR, VOIP?
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000858
Erik Språngca28fdc2015-08-31 14:00:50 +0200859 PacketBuiltCallback callback(ctx);
860 if (!callback.BuildPacket(xr))
861 return BuildResult::kTruncated;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000862
Erik Språng242e22b2015-05-11 10:17:43 +0200863 return BuildResult::kSuccess;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000864}
865
Erik Språng242e22b2015-05-11 10:17:43 +0200866RTCPSender::BuildResult RTCPSender::BuildDlrr(RtcpContext* ctx) {
Erik Språngca28fdc2015-08-31 14:00:50 +0200867 rtcp::Xr xr;
868 xr.From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000869
Erik Språngca28fdc2015-08-31 14:00:50 +0200870 rtcp::Dlrr dlrr;
Erik Språng242e22b2015-05-11 10:17:43 +0200871 const RtcpReceiveTimeInfo& info = ctx->feedback_state.last_xr_rr;
Erik Språngca28fdc2015-08-31 14:00:50 +0200872 dlrr.WithDlrrItem(info.sourceSSRC, info.lastRR, info.delaySinceLastRR);
873
874 xr.WithDlrr(&dlrr);
875
876 PacketBuiltCallback callback(ctx);
877 if (!callback.BuildPacket(xr))
878 return BuildResult::kTruncated;
Erik Språng242e22b2015-05-11 10:17:43 +0200879
880 return BuildResult::kSuccess;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000881}
882
Erik Språng242e22b2015-05-11 10:17:43 +0200883// TODO(sprang): Add a unit test for this, or remove if the code isn't used.
884RTCPSender::BuildResult RTCPSender::BuildVoIPMetric(RtcpContext* ctx) {
Erik Språngca28fdc2015-08-31 14:00:50 +0200885 rtcp::Xr xr;
886 xr.From(ssrc_);
887
888 rtcp::VoipMetric voip;
889 voip.To(remote_ssrc_);
890 voip.LossRate(xr_voip_metric_.lossRate);
891 voip.DiscardRate(xr_voip_metric_.discardRate);
892 voip.BurstDensity(xr_voip_metric_.burstDensity);
893 voip.GapDensity(xr_voip_metric_.gapDensity);
894 voip.BurstDuration(xr_voip_metric_.burstDuration);
895 voip.GapDuration(xr_voip_metric_.gapDuration);
896 voip.RoundTripDelay(xr_voip_metric_.roundTripDelay);
897 voip.EndSystemDelay(xr_voip_metric_.endSystemDelay);
898 voip.SignalLevel(xr_voip_metric_.signalLevel);
899 voip.NoiseLevel(xr_voip_metric_.noiseLevel);
900 voip.Rerl(xr_voip_metric_.RERL);
901 voip.Gmin(xr_voip_metric_.Gmin);
902 voip.Rfactor(xr_voip_metric_.Rfactor);
903 voip.ExtRfactor(xr_voip_metric_.extRfactor);
904 voip.MosLq(xr_voip_metric_.MOSLQ);
905 voip.MosCq(xr_voip_metric_.MOSCQ);
906 voip.RxConfig(xr_voip_metric_.RXconfig);
907 voip.JbNominal(xr_voip_metric_.JBnominal);
908 voip.JbMax(xr_voip_metric_.JBmax);
909 voip.JbAbsMax(xr_voip_metric_.JBabsMax);
910
911 xr.WithVoipMetric(&voip);
912
913 PacketBuiltCallback callback(ctx);
914 if (!callback.BuildPacket(xr))
Erik Språng242e22b2015-05-11 10:17:43 +0200915 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000916
Erik Språng242e22b2015-05-11 10:17:43 +0200917 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000918}
919
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000920int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200921 RTCPPacketType packetType,
922 int32_t nack_size,
923 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000924 bool repeat,
925 uint64_t pictureID) {
Erik Språng242e22b2015-05-11 10:17:43 +0200926 return SendCompoundRTCP(
927 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
928 nack_size, nack_list, repeat, pictureID);
929}
930
931int32_t RTCPSender::SendCompoundRTCP(
932 const FeedbackState& feedback_state,
933 const std::set<RTCPPacketType>& packetTypes,
934 int32_t nack_size,
935 const uint16_t* nack_list,
936 bool repeat,
937 uint64_t pictureID) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000938 {
Erik Språng242e22b2015-05-11 10:17:43 +0200939 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
pbosda903ea2015-10-02 02:36:56 -0700940 if (method_ == RtcpMode::kOff) {
Erik Språng61be2a42015-04-27 13:32:52 +0200941 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
942 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +0000943 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000944 }
945 uint8_t rtcp_buffer[IP_PACKET_SIZE];
Erik Språng242e22b2015-05-11 10:17:43 +0200946 int rtcp_length =
947 PrepareRTCP(feedback_state, packetTypes, nack_size, nack_list, repeat,
948 pictureID, rtcp_buffer, IP_PACKET_SIZE);
Erik Språng61be2a42015-04-27 13:32:52 +0200949
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000950 // Sanity don't send empty packets.
Erik Språng242e22b2015-05-11 10:17:43 +0200951 if (rtcp_length <= 0)
952 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200953
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000954 return SendToNetwork(rtcp_buffer, static_cast<size_t>(rtcp_length));
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000955}
956
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000957int RTCPSender::PrepareRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200958 const std::set<RTCPPacketType>& packetTypes,
959 int32_t nack_size,
960 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000961 bool repeat,
962 uint64_t pictureID,
963 uint8_t* rtcp_buffer,
964 int buffer_size) {
Erik Språng242e22b2015-05-11 10:17:43 +0200965 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000966
Erik Språng242e22b2015-05-11 10:17:43 +0200967 RtcpContext context(feedback_state, nack_size, nack_list, repeat, pictureID,
968 rtcp_buffer, buffer_size);
969
970 // Add all flags as volatile. Non volatile entries will not be overwritten
971 // and all new volatile flags added will be consumed by the end of this call.
972 SetFlags(packetTypes, true);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000973
Erik Språng61be2a42015-04-27 13:32:52 +0200974 if (packet_type_counter_.first_packet_time_ms == -1)
Erik Språng242e22b2015-05-11 10:17:43 +0200975 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språng61be2a42015-04-27 13:32:52 +0200976
Erik Språng242e22b2015-05-11 10:17:43 +0200977 bool generate_report;
978 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
979 // Report type already explicitly set, don't automatically populate.
980 generate_report = true;
henrikg91d6ede2015-09-17 00:24:34 -0700981 RTC_DCHECK(ConsumeFlag(kRtcpReport) == false);
Erik Språng242e22b2015-05-11 10:17:43 +0200982 } else {
983 generate_report =
pbosda903ea2015-10-02 02:36:56 -0700984 (ConsumeFlag(kRtcpReport) && method_ == RtcpMode::kReducedSize) ||
985 method_ == RtcpMode::kCompound;
Erik Språng242e22b2015-05-11 10:17:43 +0200986 if (generate_report)
987 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000988 }
989
Erik Språng0ea42d32015-06-25 14:46:16 +0200990 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
Erik Språng242e22b2015-05-11 10:17:43 +0200991 SetFlag(kRtcpSdes, true);
992
993 // We need to send our NTP even if we haven't received any reports.
994 clock_->CurrentNtp(context.ntp_sec, context.ntp_frac);
995
996 if (generate_report) {
997 if (!sending_ && xr_send_receiver_reference_time_enabled_)
998 SetFlag(kRtcpXrReceiverReferenceTime, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200999 if (feedback_state.has_last_xr_rr)
Erik Språng242e22b2015-05-11 10:17:43 +02001000 SetFlag(kRtcpXrDlrrReportBlock, true);
1001
1002 // generate next time to send an RTCP report
Erik Språng61be2a42015-04-27 13:32:52 +02001003 // seeded from RTP constructor
1004 int32_t random = rand() % 1000;
1005 int32_t timeToNext = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001006
Erik Språng242e22b2015-05-11 10:17:43 +02001007 if (audio_) {
Erik Språng61be2a42015-04-27 13:32:52 +02001008 timeToNext = (RTCP_INTERVAL_AUDIO_MS / 2) +
1009 (RTCP_INTERVAL_AUDIO_MS * random / 1000);
1010 } else {
1011 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
Erik Språng242e22b2015-05-11 10:17:43 +02001012 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +02001013 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
1014 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
1015 if (send_bitrate_kbit != 0)
1016 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001017 }
Erik Språng61be2a42015-04-27 13:32:52 +02001018 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
1019 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
1020 timeToNext = (minIntervalMs / 2) + (minIntervalMs * random / 1000);
1021 }
Erik Språng242e22b2015-05-11 10:17:43 +02001022 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001023
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001024 StatisticianMap statisticians =
1025 receive_statistics_->GetActiveStatisticians();
1026 if (!statisticians.empty()) {
Erik Språng61be2a42015-04-27 13:32:52 +02001027 for (auto it = statisticians.begin(); it != statisticians.end(); ++it) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001028 RTCPReportBlock report_block;
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001029 if (PrepareReport(feedback_state, it->first, it->second,
1030 &report_block)) {
danilchapdf948f02015-11-13 03:03:13 -08001031 // TODO(danilchap) AddReportBlock may fail (for 2 different reasons).
1032 // Probably it shouldn't be ignored.
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001033 AddReportBlock(report_block);
Erik Språng61be2a42015-04-27 13:32:52 +02001034 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001035 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001036 }
1037 }
1038
Erik Språng242e22b2015-05-11 10:17:43 +02001039 auto it = report_flags_.begin();
1040 while (it != report_flags_.end()) {
1041 auto builder = builders_.find(it->type);
henrikg91d6ede2015-09-17 00:24:34 -07001042 RTC_DCHECK(builder != builders_.end());
Erik Språng242e22b2015-05-11 10:17:43 +02001043 if (it->is_volatile) {
1044 report_flags_.erase(it++);
1045 } else {
1046 ++it;
Erik Språng61be2a42015-04-27 13:32:52 +02001047 }
Erik Språng242e22b2015-05-11 10:17:43 +02001048
1049 uint32_t start_position = context.position;
Erik Språng0ea42d32015-06-25 14:46:16 +02001050 BuildResult result = (this->*(builder->second))(&context);
Erik Språng242e22b2015-05-11 10:17:43 +02001051 switch (result) {
1052 case BuildResult::kError:
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001053 return -1;
Erik Språng242e22b2015-05-11 10:17:43 +02001054 case BuildResult::kTruncated:
1055 return context.position;
1056 case BuildResult::kAborted:
1057 context.position = start_position;
1058 FALLTHROUGH();
1059 case BuildResult::kSuccess:
1060 continue;
Erik Språng61be2a42015-04-27 13:32:52 +02001061 default:
Erik Språng242e22b2015-05-11 10:17:43 +02001062 abort();
Erik Språng61be2a42015-04-27 13:32:52 +02001063 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001064 }
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001065
1066 if (packet_type_counter_observer_ != NULL) {
1067 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
Erik Språng242e22b2015-05-11 10:17:43 +02001068 remote_ssrc_, packet_type_counter_);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001069 }
1070
henrikg91d6ede2015-09-17 00:24:34 -07001071 RTC_DCHECK(AllVolatileFlagsConsumed());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001072
Erik Språng242e22b2015-05-11 10:17:43 +02001073 return context.position;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001074}
1075
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001076bool RTCPSender::PrepareReport(const FeedbackState& feedback_state,
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001077 uint32_t ssrc,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001078 StreamStatistician* statistician,
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001079 RTCPReportBlock* report_block) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001080 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +00001081 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001082 if (!statistician->GetStatistics(&stats, true))
1083 return false;
1084 report_block->fractionLost = stats.fraction_lost;
1085 report_block->cumulativeLost = stats.cumulative_lost;
1086 report_block->extendedHighSeqNum =
1087 stats.extended_max_sequence_number;
1088 report_block->jitter = stats.jitter;
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001089 report_block->remoteSSRC = ssrc;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001090
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001091 // TODO(sprang): Do we really need separate time stamps for each report?
1092 // Get our NTP as late as possible to avoid a race.
1093 uint32_t ntp_secs;
1094 uint32_t ntp_frac;
1095 clock_->CurrentNtp(ntp_secs, ntp_frac);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001096
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001097 // Delay since last received report.
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001098 uint32_t delaySinceLastReceivedSR = 0;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001099 if ((feedback_state.last_rr_ntp_secs != 0) ||
1100 (feedback_state.last_rr_ntp_frac != 0)) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001101 // Get the 16 lowest bits of seconds and the 16 highest bits of fractions.
1102 uint32_t now = ntp_secs & 0x0000FFFF;
Erik Språng61be2a42015-04-27 13:32:52 +02001103 now <<= 16;
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001104 now += (ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001105
Erik Språng61be2a42015-04-27 13:32:52 +02001106 uint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
1107 receiveTime <<= 16;
1108 receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001109
1110 delaySinceLastReceivedSR = now-receiveTime;
1111 }
1112 report_block->delaySinceLastSR = delaySinceLastReceivedSR;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001113 report_block->lastSR = feedback_state.remote_sr;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001114 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +00001115}
1116
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001117int32_t RTCPSender::SendToNetwork(const uint8_t* dataBuffer, size_t length) {
sprang86fd9ed2015-09-29 04:45:43 -07001118 if (transport_->SendRtcp(dataBuffer, length))
1119 return 0;
Erik Språng61be2a42015-04-27 13:32:52 +02001120 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001121}
1122
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001123void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
1124 assert(csrcs.size() <= kRtpCsrcSize);
Erik Språng242e22b2015-05-11 10:17:43 +02001125 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001126 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +00001127}
1128
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001129int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
1130 uint32_t name,
1131 const uint8_t* data,
1132 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +02001133 if (length % 4 != 0) {
1134 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
1135 return -1;
1136 }
Erik Språng242e22b2015-05-11 10:17:43 +02001137 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +00001138
Erik Språng242e22b2015-05-11 10:17:43 +02001139 SetFlag(kRtcpApp, true);
1140 app_sub_type_ = subType;
1141 app_name_ = name;
1142 app_data_.reset(new uint8_t[length]);
1143 app_length_ = length;
1144 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +02001145 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001146}
1147
Erik Språng61be2a42015-04-27 13:32:52 +02001148int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
Erik Språng242e22b2015-05-11 10:17:43 +02001149 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1150 memcpy(&xr_voip_metric_, VoIPMetric, sizeof(RTCPVoIPMetric));
niklase@google.com470e71d2011-07-07 08:21:25 +00001151
Erik Språng242e22b2015-05-11 10:17:43 +02001152 SetFlag(kRtcpXrVoipMetric, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001153 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001154}
1155
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001156void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +02001157 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1158 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001159}
1160
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00001161bool RTCPSender::RtcpXrReceiverReferenceTime() const {
Erik Språng242e22b2015-05-11 10:17:43 +02001162 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1163 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00001164}
1165
niklase@google.com470e71d2011-07-07 08:21:25 +00001166// no callbacks allowed inside this function
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001167int32_t RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
1168 uint32_t maxBitrateKbit) {
Erik Språng242e22b2015-05-11 10:17:43 +02001169 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +00001170
Erik Språng242e22b2015-05-11 10:17:43 +02001171 if (0 == tmmbr_help_.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit)) {
1172 SetFlag(kRtcpTmmbn, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001173 return 0;
1174 }
1175 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001176}
Erik Språng61be2a42015-04-27 13:32:52 +02001177
Erik Språng242e22b2015-05-11 10:17:43 +02001178void RTCPSender::SetFlag(RTCPPacketType type, bool is_volatile) {
1179 report_flags_.insert(ReportFlag(type, is_volatile));
1180}
1181
1182void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
1183 bool is_volatile) {
1184 for (RTCPPacketType type : types)
1185 SetFlag(type, is_volatile);
1186}
1187
1188bool RTCPSender::IsFlagPresent(RTCPPacketType type) const {
1189 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
1190}
1191
1192bool RTCPSender::ConsumeFlag(RTCPPacketType type, bool forced) {
1193 auto it = report_flags_.find(ReportFlag(type, false));
1194 if (it == report_flags_.end())
1195 return false;
1196 if (it->is_volatile || forced)
1197 report_flags_.erase((it));
1198 return true;
1199}
1200
1201bool RTCPSender::AllVolatileFlagsConsumed() const {
1202 for (const ReportFlag& flag : report_flags_) {
1203 if (flag.is_volatile)
1204 return false;
1205 }
1206 return true;
1207}
1208
sprang233bd872015-09-08 13:25:16 -07001209bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
sprang233bd872015-09-08 13:25:16 -07001210 class Sender : public rtcp::RtcpPacket::PacketReadyCallback {
1211 public:
Peter Boströmac547a62015-09-17 23:03:57 +02001212 Sender(Transport* transport)
1213 : transport_(transport), send_failure_(false) {}
sprang233bd872015-09-08 13:25:16 -07001214
1215 void OnPacketReady(uint8_t* data, size_t length) override {
pbos2d566682015-09-28 09:59:31 -07001216 if (!transport_->SendRtcp(data, length))
sprang233bd872015-09-08 13:25:16 -07001217 send_failure_ = true;
1218 }
1219
1220 Transport* const transport_;
sprang233bd872015-09-08 13:25:16 -07001221 bool send_failure_;
sprang86fd9ed2015-09-29 04:45:43 -07001222 } sender(transport_);
sprang233bd872015-09-08 13:25:16 -07001223
1224 uint8_t buffer[IP_PACKET_SIZE];
1225 return packet.BuildExternalBuffer(buffer, IP_PACKET_SIZE, &sender) &&
1226 !sender.send_failure_;
1227}
1228
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001229} // namespace webrtc