blob: 6967754fe62f737e73f450314da31bf1ebd9dcdd [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000011#include "webrtc/modules/rtp_rtcp/source/rtcp_sender.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000013#include <assert.h> // assert
14#include <stdlib.h> // rand
stefan@webrtc.org9354cc92012-06-07 08:10:14 +000015#include <string.h> // memcpy
niklase@google.com470e71d2011-07-07 08:21:25 +000016
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000017#include <algorithm> // min
Erik Språng61be2a42015-04-27 13:32:52 +020018#include <limits> // max
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000019
Erik Språng61be2a42015-04-27 13:32:52 +020020#include "webrtc/base/checks.h"
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000021#include "webrtc/common_types.h"
sprang@webrtc.org779c3d12015-03-17 16:42:49 +000022#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000023#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
24#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +000025#include "webrtc/system_wrappers/interface/logging.h"
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000026#include "webrtc/system_wrappers/interface/trace_event.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000027
niklase@google.com470e71d2011-07-07 08:21:25 +000028namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000029
30using RTCPUtility::RTCPCnameInformation;
31
Erik Språng61be2a42015-04-27 13:32:52 +020032NACKStringBuilder::NACKStringBuilder()
Erik Språng242e22b2015-05-11 10:17:43 +020033 : stream_(""), count_(0), prevNack_(0), consecutive_(false) {
edjee@google.com79b02892013-04-04 19:43:34 +000034}
35
pbos@webrtc.orgf3e4cee2013-07-31 15:17:19 +000036NACKStringBuilder::~NACKStringBuilder() {}
37
pbos@webrtc.org2f446732013-04-08 11:08:41 +000038void NACKStringBuilder::PushNACK(uint16_t nack)
edjee@google.com79b02892013-04-04 19:43:34 +000039{
Erik Språng242e22b2015-05-11 10:17:43 +020040 if (count_ == 0) {
41 stream_ << nack;
42 } else if (nack == prevNack_ + 1) {
43 consecutive_ = true;
Erik Språng61be2a42015-04-27 13:32:52 +020044 } else {
Erik Språng242e22b2015-05-11 10:17:43 +020045 if (consecutive_) {
46 stream_ << "-" << prevNack_;
47 consecutive_ = false;
edjee@google.com79b02892013-04-04 19:43:34 +000048 }
Erik Språng242e22b2015-05-11 10:17:43 +020049 stream_ << "," << nack;
Erik Språng61be2a42015-04-27 13:32:52 +020050 }
Erik Språng242e22b2015-05-11 10:17:43 +020051 count_++;
52 prevNack_ = nack;
edjee@google.com79b02892013-04-04 19:43:34 +000053}
54
Erik Språng61be2a42015-04-27 13:32:52 +020055std::string NACKStringBuilder::GetResult() {
Erik Språng242e22b2015-05-11 10:17:43 +020056 if (consecutive_) {
57 stream_ << "-" << prevNack_;
58 consecutive_ = false;
Erik Språng61be2a42015-04-27 13:32:52 +020059 }
Erik Språng242e22b2015-05-11 10:17:43 +020060 return stream_.str();
edjee@google.com79b02892013-04-04 19:43:34 +000061}
62
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000063RTCPSender::FeedbackState::FeedbackState()
64 : send_payload_type(0),
65 frequency_hz(0),
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +000066 packets_sent(0),
67 media_bytes_sent(0),
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000068 send_bitrate(0),
69 last_rr_ntp_secs(0),
70 last_rr_ntp_frac(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000071 remote_sr(0),
Erik Språng61be2a42015-04-27 13:32:52 +020072 has_last_xr_rr(false),
73 module(nullptr) {
74}
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000075
Erik Språng242e22b2015-05-11 10:17:43 +020076struct RTCPSender::RtcpContext {
77 RtcpContext(const FeedbackState& feedback_state,
78 int32_t nack_size,
79 const uint16_t* nack_list,
80 bool repeat,
81 uint64_t picture_id,
82 uint8_t* buffer,
83 uint32_t buffer_size)
84 : feedback_state(feedback_state),
85 nack_size(nack_size),
86 nack_list(nack_list),
87 repeat(repeat),
88 picture_id(picture_id),
89 buffer(buffer),
90 buffer_size(buffer_size),
91 ntp_sec(0),
92 ntp_frac(0),
Erik Språng242e22b2015-05-11 10:17:43 +020093 position(0) {}
94
95 uint8_t* AllocateData(uint32_t bytes) {
96 DCHECK_LE(position + bytes, buffer_size);
97 uint8_t* ptr = &buffer[position];
98 position += bytes;
99 return ptr;
100 }
101
102 const FeedbackState& feedback_state;
103 int32_t nack_size;
104 const uint16_t* nack_list;
105 bool repeat;
106 uint64_t picture_id;
107 uint8_t* buffer;
108 uint32_t buffer_size;
109 uint32_t ntp_sec;
110 uint32_t ntp_frac;
Erik Språng242e22b2015-05-11 10:17:43 +0200111 uint32_t position;
112};
113
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200114// TODO(sprang): Once all builders use RtcpPacket, call SendToNetwork() here.
115class RTCPSender::PacketBuiltCallback
116 : public rtcp::RtcpPacket::PacketReadyCallback {
117 public:
118 PacketBuiltCallback(RtcpContext* context) : context_(context) {}
119 virtual ~PacketBuiltCallback() {}
120 void OnPacketReady(uint8_t* data, size_t length) override {
121 context_->position += length;
122 }
Erik Språng72aa9a62015-07-31 16:16:02 +0200123 bool BuildPacket(const rtcp::RtcpPacket& packet) {
124 return packet.BuildExternalBuffer(
125 &context_->buffer[context_->position],
126 context_->buffer_size - context_->position, this);
127 }
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200128
129 private:
130 RtcpContext* const context_;
131};
132
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000133RTCPSender::RTCPSender(
134 int32_t id,
135 bool audio,
136 Clock* clock,
137 ReceiveStatistics* receive_statistics,
138 RtcpPacketTypeCounterObserver* packet_type_counter_observer)
Erik Språng242e22b2015-05-11 10:17:43 +0200139 : id_(id),
140 audio_(audio),
141 clock_(clock),
142 method_(kRtcpOff),
143 critical_section_transport_(
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000144 CriticalSectionWrapper::CreateCriticalSection()),
Erik Språng242e22b2015-05-11 10:17:43 +0200145 cbTransport_(nullptr),
niklase@google.com470e71d2011-07-07 08:21:25 +0000146
Erik Språng242e22b2015-05-11 10:17:43 +0200147 critical_section_rtcp_sender_(
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000148 CriticalSectionWrapper::CreateCriticalSection()),
Erik Språng242e22b2015-05-11 10:17:43 +0200149 using_nack_(false),
150 sending_(false),
151 remb_enabled_(false),
Erik Språng242e22b2015-05-11 10:17:43 +0200152 next_time_to_send_rtcp_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000153 start_timestamp_(0),
154 last_rtp_timestamp_(0),
155 last_frame_capture_time_ms_(-1),
Erik Språng242e22b2015-05-11 10:17:43 +0200156 ssrc_(0),
157 remote_ssrc_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000158 receive_statistics_(receive_statistics),
niklase@google.com470e71d2011-07-07 08:21:25 +0000159
Erik Språng242e22b2015-05-11 10:17:43 +0200160 sequence_number_fir_(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000161
Erik Språng242e22b2015-05-11 10:17:43 +0200162 remb_bitrate_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000163
Erik Språng242e22b2015-05-11 10:17:43 +0200164 tmmbr_help_(),
165 tmmbr_send_(0),
166 packet_oh_send_(0),
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000167
Erik Språng242e22b2015-05-11 10:17:43 +0200168 app_sub_type_(0),
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200169 app_name_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200170 app_data_(nullptr),
171 app_length_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000172
Erik Språng242e22b2015-05-11 10:17:43 +0200173 xr_send_receiver_reference_time_enabled_(false),
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000174 packet_type_counter_observer_(packet_type_counter_observer) {
Erik Språng242e22b2015-05-11 10:17:43 +0200175 memset(last_send_report_, 0, sizeof(last_send_report_));
176 memset(last_rtcp_time_, 0, sizeof(last_rtcp_time_));
177
178 builders_[kRtcpSr] = &RTCPSender::BuildSR;
179 builders_[kRtcpRr] = &RTCPSender::BuildRR;
Erik Språng0ea42d32015-06-25 14:46:16 +0200180 builders_[kRtcpSdes] = &RTCPSender::BuildSDES;
Erik Språng242e22b2015-05-11 10:17:43 +0200181 builders_[kRtcpPli] = &RTCPSender::BuildPLI;
182 builders_[kRtcpFir] = &RTCPSender::BuildFIR;
183 builders_[kRtcpSli] = &RTCPSender::BuildSLI;
184 builders_[kRtcpRpsi] = &RTCPSender::BuildRPSI;
185 builders_[kRtcpRemb] = &RTCPSender::BuildREMB;
186 builders_[kRtcpBye] = &RTCPSender::BuildBYE;
187 builders_[kRtcpApp] = &RTCPSender::BuildAPP;
188 builders_[kRtcpTmmbr] = &RTCPSender::BuildTMMBR;
189 builders_[kRtcpTmmbn] = &RTCPSender::BuildTMMBN;
190 builders_[kRtcpNack] = &RTCPSender::BuildNACK;
191 builders_[kRtcpXrVoipMetric] = &RTCPSender::BuildVoIPMetric;
192 builders_[kRtcpXrReceiverReferenceTime] =
193 &RTCPSender::BuildReceiverReferenceTime;
194 builders_[kRtcpXrDlrrReportBlock] = &RTCPSender::BuildDlrr;
niklase@google.com470e71d2011-07-07 08:21:25 +0000195}
196
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000197RTCPSender::~RTCPSender() {
niklase@google.com470e71d2011-07-07 08:21:25 +0000198}
199
Erik Språng61be2a42015-04-27 13:32:52 +0200200int32_t RTCPSender::RegisterSendTransport(Transport* outgoingTransport) {
Erik Språng242e22b2015-05-11 10:17:43 +0200201 CriticalSectionScoped lock(critical_section_transport_.get());
202 cbTransport_ = outgoingTransport;
Erik Språng61be2a42015-04-27 13:32:52 +0200203 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000204}
205
Erik Språng61be2a42015-04-27 13:32:52 +0200206RTCPMethod RTCPSender::Status() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200207 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
208 return method_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000209}
210
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000211void RTCPSender::SetRTCPStatus(RTCPMethod method) {
Erik Språng242e22b2015-05-11 10:17:43 +0200212 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
213 method_ = method;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000214
215 if (method == kRtcpOff)
216 return;
Erik Språng242e22b2015-05-11 10:17:43 +0200217 next_time_to_send_rtcp_ =
218 clock_->TimeInMilliseconds() +
219 (audio_ ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000220}
221
Erik Språng61be2a42015-04-27 13:32:52 +0200222bool RTCPSender::Sending() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200223 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
224 return sending_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000225}
226
Erik Språng61be2a42015-04-27 13:32:52 +0200227int32_t RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
228 bool sending) {
229 bool sendRTCPBye = false;
230 {
Erik Språng242e22b2015-05-11 10:17:43 +0200231 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000232
Erik Språng242e22b2015-05-11 10:17:43 +0200233 if (method_ != kRtcpOff) {
234 if (sending == false && sending_ == true) {
Erik Språng61be2a42015-04-27 13:32:52 +0200235 // Trigger RTCP bye
236 sendRTCPBye = true;
237 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000238 }
Erik Språng242e22b2015-05-11 10:17:43 +0200239 sending_ = sending;
Erik Språng61be2a42015-04-27 13:32:52 +0200240 }
241 if (sendRTCPBye)
242 return SendRTCP(feedback_state, kRtcpBye);
243 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000244}
245
Erik Språng61be2a42015-04-27 13:32:52 +0200246bool RTCPSender::REMB() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200247 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
248 return remb_enabled_;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000249}
250
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000251void RTCPSender::SetREMBStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200252 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
253 remb_enabled_ = enable;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000254}
255
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000256void RTCPSender::SetREMBData(uint32_t bitrate,
257 const std::vector<uint32_t>& ssrcs) {
Erik Språng242e22b2015-05-11 10:17:43 +0200258 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
259 remb_bitrate_ = bitrate;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000260 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000261
Erik Språng242e22b2015-05-11 10:17:43 +0200262 if (remb_enabled_)
263 SetFlag(kRtcpRemb, false);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000264 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
265 // throttled by the caller.
Erik Språng242e22b2015-05-11 10:17:43 +0200266 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000267}
268
Erik Språng61be2a42015-04-27 13:32:52 +0200269bool RTCPSender::TMMBR() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200270 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
271 return IsFlagPresent(RTCPPacketType::kRtcpTmmbr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000272}
273
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000274void RTCPSender::SetTMMBRStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200275 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
276 if (enable) {
277 SetFlag(RTCPPacketType::kRtcpTmmbr, false);
278 } else {
279 ConsumeFlag(RTCPPacketType::kRtcpTmmbr, true);
280 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000281}
282
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000283void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
Erik Språng242e22b2015-05-11 10:17:43 +0200284 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000285 start_timestamp_ = start_timestamp;
286}
287
288void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
289 int64_t capture_time_ms) {
Erik Språng242e22b2015-05-11 10:17:43 +0200290 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000291 last_rtp_timestamp_ = rtp_timestamp;
292 if (capture_time_ms < 0) {
293 // We don't currently get a capture time from VoiceEngine.
Erik Språng242e22b2015-05-11 10:17:43 +0200294 last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000295 } else {
296 last_frame_capture_time_ms_ = capture_time_ms;
297 }
298}
299
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000300void RTCPSender::SetSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200301 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000302
Erik Språng242e22b2015-05-11 10:17:43 +0200303 if (ssrc_ != 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200304 // not first SetSSRC, probably due to a collision
305 // schedule a new RTCP report
306 // make sure that we send a RTP packet
Erik Språng242e22b2015-05-11 10:17:43 +0200307 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
Erik Språng61be2a42015-04-27 13:32:52 +0200308 }
Erik Språng242e22b2015-05-11 10:17:43 +0200309 ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000310}
311
Erik Språng61be2a42015-04-27 13:32:52 +0200312void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200313 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
314 remote_ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000315}
316
Peter Boström9ba52f82015-06-01 14:12:28 +0200317int32_t RTCPSender::SetCNAME(const char* c_name) {
318 if (!c_name)
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000319 return -1;
320
Peter Boström9ba52f82015-06-01 14:12:28 +0200321 DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
Erik Språng242e22b2015-05-11 10:17:43 +0200322 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200323 cname_ = c_name;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000324 return 0;
325}
326
Erik Språng0ea42d32015-06-25 14:46:16 +0200327int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC, const char* c_name) {
328 assert(c_name);
329 DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
Erik Språng242e22b2015-05-11 10:17:43 +0200330 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200331 if (csrc_cnames_.size() >= kRtpCsrcSize)
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000332 return -1;
Erik Språng0ea42d32015-06-25 14:46:16 +0200333
334 csrc_cnames_[SSRC] = c_name;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000335 return 0;
336}
337
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000338int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
Erik Språng242e22b2015-05-11 10:17:43 +0200339 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200340 auto it = csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000341
Erik Språng242e22b2015-05-11 10:17:43 +0200342 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000343 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200344
Erik Språng242e22b2015-05-11 10:17:43 +0200345 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000346 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000347}
348
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000349bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
niklase@google.com470e71d2011-07-07 08:21:25 +0000350/*
351 For audio we use a fix 5 sec interval
352
353 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000354 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
355 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000356
357
358From RFC 3550
359
360 MAX RTCP BW is 5% if the session BW
361 A send report is approximately 65 bytes inc CNAME
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000362 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000363
364 The RECOMMENDED value for the reduced minimum in seconds is 360
365 divided by the session bandwidth in kilobits/second. This minimum
366 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
367
368 If the participant has not yet sent an RTCP packet (the variable
369 initial is true), the constant Tmin is set to 2.5 seconds, else it
370 is set to 5 seconds.
371
372 The interval between RTCP packets is varied randomly over the
373 range [0.5,1.5] times the calculated interval to avoid unintended
374 synchronization of all participants
375
376 if we send
377 If the participant is a sender (we_sent true), the constant C is
378 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
379 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
380 number of senders.
381
382 if we receive only
383 If we_sent is not true, the constant C is set
384 to the average RTCP packet size divided by 75% of the RTCP
385 bandwidth. The constant n is set to the number of receivers
386 (members - senders). If the number of senders is greater than
387 25%, senders and receivers are treated together.
388
389 reconsideration NOT required for peer-to-peer
390 "timer reconsideration" is
391 employed. This algorithm implements a simple back-off mechanism
392 which causes users to hold back RTCP packet transmission if the
393 group sizes are increasing.
394
395 n = number of members
396 C = avg_size/(rtcpBW/4)
397
398 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
399
400 4. The calculated interval T is set to a number uniformly distributed
401 between 0.5 and 1.5 times the deterministic calculated interval.
402
403 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
404 for the fact that the timer reconsideration algorithm converges to
405 a value of the RTCP bandwidth below the intended average
406*/
407
Erik Språng242e22b2015-05-11 10:17:43 +0200408 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000409
Erik Språng242e22b2015-05-11 10:17:43 +0200410 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
xians@webrtc.org8738d272011-11-25 13:43:53 +0000411
Erik Språng242e22b2015-05-11 10:17:43 +0200412 if (method_ == kRtcpOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000413 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000414
Erik Språng242e22b2015-05-11 10:17:43 +0200415 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200416 // for video key-frames we want to send the RTCP before the large key-frame
417 // if we have a 100 ms margin
418 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
419 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000420
Erik Språng242e22b2015-05-11 10:17:43 +0200421 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200422 return true;
423 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200424 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200425 // wrap
426 return true;
427 }
428 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000429}
430
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000431int64_t RTCPSender::SendTimeOfSendReport(uint32_t sendReport) {
Erik Språng242e22b2015-05-11 10:17:43 +0200432 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000433
Erik Språng61be2a42015-04-27 13:32:52 +0200434 // This is only saved when we are the sender
Erik Språng242e22b2015-05-11 10:17:43 +0200435 if ((last_send_report_[0] == 0) || (sendReport == 0)) {
Erik Språng61be2a42015-04-27 13:32:52 +0200436 return 0; // will be ignored
437 } else {
438 for (int i = 0; i < RTCP_NUMBER_OF_SR; ++i) {
Erik Språng242e22b2015-05-11 10:17:43 +0200439 if (last_send_report_[i] == sendReport)
440 return last_rtcp_time_[i];
niklase@google.com470e71d2011-07-07 08:21:25 +0000441 }
Erik Språng61be2a42015-04-27 13:32:52 +0200442 }
443 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000444}
445
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000446bool RTCPSender::SendTimeOfXrRrReport(uint32_t mid_ntp,
447 int64_t* time_ms) const {
Erik Språng242e22b2015-05-11 10:17:43 +0200448 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000449
450 if (last_xr_rr_.empty()) {
451 return false;
452 }
453 std::map<uint32_t, int64_t>::const_iterator it = last_xr_rr_.find(mid_ntp);
454 if (it == last_xr_rr_.end()) {
455 return false;
456 }
457 *time_ms = it->second;
458 return true;
459}
460
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200461int32_t RTCPSender::AddReportBlock(const RTCPReportBlock& report_block) {
462 if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000463 LOG(LS_WARNING) << "Too many report blocks.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000464 return -1;
465 }
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200466 rtcp::ReportBlock* block = &report_blocks_[report_block.remoteSSRC];
467 block->To(report_block.remoteSSRC);
468 block->WithFractionLost(report_block.fractionLost);
469 block->WithCumulativeLost(report_block.cumulativeLost);
470 block->WithExtHighestSeqNum(report_block.extendedHighSeqNum);
471 block->WithJitter(report_block.jitter);
472 block->WithLastSr(report_block.lastSR);
473 block->WithDelayLastSr(report_block.delaySinceLastSR);
474
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000475 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000476}
477
Erik Språng242e22b2015-05-11 10:17:43 +0200478RTCPSender::BuildResult RTCPSender::BuildSR(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200479 for (int i = (RTCP_NUMBER_OF_SR - 2); i >= 0; i--) {
480 // shift old
Erik Språng242e22b2015-05-11 10:17:43 +0200481 last_send_report_[i + 1] = last_send_report_[i];
482 last_rtcp_time_[i + 1] = last_rtcp_time_[i];
Erik Språng61be2a42015-04-27 13:32:52 +0200483 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000484
Erik Språng242e22b2015-05-11 10:17:43 +0200485 last_rtcp_time_[0] = Clock::NtpToMs(ctx->ntp_sec, ctx->ntp_frac);
486 last_send_report_[0] = (ctx->ntp_sec << 16) + (ctx->ntp_frac >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000487
Erik Språng61be2a42015-04-27 13:32:52 +0200488 // The timestamp of this RTCP packet should be estimated as the timestamp of
489 // the frame being captured at this moment. We are calculating that
490 // timestamp as the last frame's timestamp + the time since the last frame
491 // was captured.
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200492 uint32_t rtp_timestamp =
493 start_timestamp_ + last_rtp_timestamp_ +
494 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) *
495 (ctx->feedback_state.frequency_hz / 1000);
niklase@google.com470e71d2011-07-07 08:21:25 +0000496
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200497 rtcp::SenderReport report;
498 report.From(ssrc_);
499 report.WithNtpSec(ctx->ntp_sec);
500 report.WithNtpFrac(ctx->ntp_frac);
501 report.WithRtpTimestamp(rtp_timestamp);
502 report.WithPacketCount(ctx->feedback_state.packets_sent);
503 report.WithOctetCount(ctx->feedback_state.media_bytes_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000504
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200505 for (auto it : report_blocks_)
506 report.WithReportBlock(it.second);
niklase@google.com470e71d2011-07-07 08:21:25 +0000507
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200508 PacketBuiltCallback callback(ctx);
Erik Språng72aa9a62015-07-31 16:16:02 +0200509 if (!callback.BuildPacket(report))
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200510 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000511
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200512 report_blocks_.clear();
Erik Språng242e22b2015-05-11 10:17:43 +0200513 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000514}
515
Erik Språng0ea42d32015-06-25 14:46:16 +0200516RTCPSender::BuildResult RTCPSender::BuildSDES(RtcpContext* ctx) {
517 size_t length_cname = cname_.length();
518 CHECK_LT(length_cname, static_cast<size_t>(RTCP_CNAME_SIZE));
niklase@google.com470e71d2011-07-07 08:21:25 +0000519
Erik Språng0ea42d32015-06-25 14:46:16 +0200520 rtcp::Sdes sdes;
521 sdes.WithCName(ssrc_, cname_);
522
523 for (const auto it : csrc_cnames_)
524 sdes.WithCName(it.first, it.second);
525
526 PacketBuiltCallback callback(ctx);
Erik Språng72aa9a62015-07-31 16:16:02 +0200527 if (!callback.BuildPacket(sdes))
Erik Språng242e22b2015-05-11 10:17:43 +0200528 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000529
Erik Språng242e22b2015-05-11 10:17:43 +0200530 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000531}
532
Erik Språng242e22b2015-05-11 10:17:43 +0200533RTCPSender::BuildResult RTCPSender::BuildRR(RtcpContext* ctx) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200534 rtcp::ReceiverReport report;
535 report.From(ssrc_);
536 for (auto it : report_blocks_)
537 report.WithReportBlock(it.second);
538
539 PacketBuiltCallback callback(ctx);
Erik Språng72aa9a62015-07-31 16:16:02 +0200540 if (!callback.BuildPacket(report))
Erik Språng242e22b2015-05-11 10:17:43 +0200541 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200542
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200543 report_blocks_.clear();
Erik Språng242e22b2015-05-11 10:17:43 +0200544
545 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000546}
547
Erik Språng242e22b2015-05-11 10:17:43 +0200548RTCPSender::BuildResult RTCPSender::BuildPLI(RtcpContext* ctx) {
Erik Språng72aa9a62015-07-31 16:16:02 +0200549 rtcp::Pli pli;
550 pli.From(ssrc_);
551 pli.To(remote_ssrc_);
552
553 PacketBuiltCallback callback(ctx);
554 if (!callback.BuildPacket(pli))
Erik Språng242e22b2015-05-11 10:17:43 +0200555 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200556
Erik Språng242e22b2015-05-11 10:17:43 +0200557 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
558 "RTCPSender::PLI");
559 ++packet_type_counter_.pli_packets;
560 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
561 ssrc_, packet_type_counter_.pli_packets);
562
563 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +0200564}
565
Erik Språng242e22b2015-05-11 10:17:43 +0200566RTCPSender::BuildResult RTCPSender::BuildFIR(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200567 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200568 if (ctx->position + 20 >= IP_PACKET_SIZE)
569 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200570
Erik Språng242e22b2015-05-11 10:17:43 +0200571 if (!ctx->repeat)
572 sequence_number_fir_++; // do not increase if repetition
niklase@google.com470e71d2011-07-07 08:21:25 +0000573
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000574 // add full intra request indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000575 uint8_t FMT = 4;
Erik Språng242e22b2015-05-11 10:17:43 +0200576 *ctx->AllocateData(1) = 0x80 + FMT;
577 *ctx->AllocateData(1) = 206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000578
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000579 //Length of 4
Erik Språng242e22b2015-05-11 10:17:43 +0200580 *ctx->AllocateData(1) = 0;
581 *ctx->AllocateData(1) = 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000582
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000583 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200584 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000585
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000586 // RFC 5104 4.3.1.2. Semantics
587 // SSRC of media source
Erik Språng242e22b2015-05-11 10:17:43 +0200588 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), 0);
niklase@google.com470e71d2011-07-07 08:21:25 +0000589
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000590 // Additional Feedback Control Information (FCI)
Erik Språng242e22b2015-05-11 10:17:43 +0200591 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remote_ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000592
Erik Språng242e22b2015-05-11 10:17:43 +0200593 *ctx->AllocateData(1) = sequence_number_fir_;
594 *ctx->AllocateData(1) = 0;
595 *ctx->AllocateData(1) = 0;
596 *ctx->AllocateData(1) = 0;
597
598 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
599 "RTCPSender::FIR");
600 ++packet_type_counter_.fir_packets;
601 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
602 ssrc_, packet_type_counter_.fir_packets);
603
604 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000605}
606
607/*
608 0 1 2 3
609 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
610 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
611 | First | Number | PictureID |
612 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
613*/
Erik Språng242e22b2015-05-11 10:17:43 +0200614RTCPSender::BuildResult RTCPSender::BuildSLI(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200615 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200616 if (ctx->position + 16 >= IP_PACKET_SIZE)
617 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000618
Erik Språng61be2a42015-04-27 13:32:52 +0200619 // add slice loss indicator
620 uint8_t FMT = 2;
Erik Språng242e22b2015-05-11 10:17:43 +0200621 *ctx->AllocateData(1) = 0x80 + FMT;
622 *ctx->AllocateData(1) = 206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000623
Erik Språng61be2a42015-04-27 13:32:52 +0200624 // Used fixed length of 3
Erik Språng242e22b2015-05-11 10:17:43 +0200625 *ctx->AllocateData(1) = 0;
626 *ctx->AllocateData(1) = 3;
niklase@google.com470e71d2011-07-07 08:21:25 +0000627
Erik Språng61be2a42015-04-27 13:32:52 +0200628 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200629 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000630
Erik Språng61be2a42015-04-27 13:32:52 +0200631 // Add the remote SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200632 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200633
634 // Add first, number & picture ID 6 bits
635 // first = 0, 13 - bits
636 // number = 0x1fff, 13 - bits only ones for now
Erik Språng242e22b2015-05-11 10:17:43 +0200637 uint32_t sliField = (0x1fff << 6) + (0x3f & ctx->picture_id);
638 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), sliField);
639
640 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000641}
642
643/*
644 0 1 2 3
645 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
646 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
647 | PB |0| Payload Type| Native RPSI bit string |
648 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
649 | defined per codec ... | Padding (0) |
650 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
651*/
652/*
653* Note: not generic made for VP8
654*/
Erik Språng242e22b2015-05-11 10:17:43 +0200655RTCPSender::BuildResult RTCPSender::BuildRPSI(RtcpContext* ctx) {
656 if (ctx->feedback_state.send_payload_type == 0xFF)
657 return BuildResult::kError;
658
Erik Språng61be2a42015-04-27 13:32:52 +0200659 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200660 if (ctx->position + 24 >= IP_PACKET_SIZE)
661 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000662
Erik Språng61be2a42015-04-27 13:32:52 +0200663 // add Reference Picture Selection Indication
664 uint8_t FMT = 3;
Erik Språng242e22b2015-05-11 10:17:43 +0200665 *ctx->AllocateData(1) = 0x80 + FMT;
666 *ctx->AllocateData(1) = 206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000667
Erik Språng61be2a42015-04-27 13:32:52 +0200668 // calc length
669 uint32_t bitsRequired = 7;
670 uint8_t bytesRequired = 1;
Erik Språng242e22b2015-05-11 10:17:43 +0200671 while ((ctx->picture_id >> bitsRequired) > 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200672 bitsRequired += 7;
673 bytesRequired++;
674 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000675
Erik Språng61be2a42015-04-27 13:32:52 +0200676 uint8_t size = 3;
677 if (bytesRequired > 6) {
678 size = 5;
679 } else if (bytesRequired > 2) {
680 size = 4;
681 }
Erik Språng242e22b2015-05-11 10:17:43 +0200682 *ctx->AllocateData(1) = 0;
683 *ctx->AllocateData(1) = size;
niklase@google.com470e71d2011-07-07 08:21:25 +0000684
Erik Språng61be2a42015-04-27 13:32:52 +0200685 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200686 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000687
Erik Språng61be2a42015-04-27 13:32:52 +0200688 // Add the remote SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200689 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200690
691 // calc padding length
692 uint8_t paddingBytes = 4 - ((2 + bytesRequired) % 4);
693 if (paddingBytes == 4)
694 paddingBytes = 0;
695 // add padding length in bits
Erik Språng242e22b2015-05-11 10:17:43 +0200696 *ctx->AllocateData(1) = paddingBytes * 8; // padding can be 0, 8, 16 or 24
Erik Språng61be2a42015-04-27 13:32:52 +0200697
698 // add payload type
Erik Språng242e22b2015-05-11 10:17:43 +0200699 *ctx->AllocateData(1) = ctx->feedback_state.send_payload_type;
Erik Språng61be2a42015-04-27 13:32:52 +0200700
701 // add picture ID
702 for (int i = bytesRequired - 1; i > 0; --i) {
Erik Språng242e22b2015-05-11 10:17:43 +0200703 *ctx->AllocateData(1) =
704 0x80 | static_cast<uint8_t>(ctx->picture_id >> (i * 7));
Erik Språng61be2a42015-04-27 13:32:52 +0200705 }
706 // add last byte of picture ID
Erik Språng242e22b2015-05-11 10:17:43 +0200707 *ctx->AllocateData(1) = static_cast<uint8_t>(ctx->picture_id & 0x7f);
niklase@google.com470e71d2011-07-07 08:21:25 +0000708
Erik Språng61be2a42015-04-27 13:32:52 +0200709 // add padding
710 for (int j = 0; j < paddingBytes; j++) {
Erik Språng242e22b2015-05-11 10:17:43 +0200711 *ctx->AllocateData(1) = 0;
Erik Språng61be2a42015-04-27 13:32:52 +0200712 }
Erik Språng242e22b2015-05-11 10:17:43 +0200713
714 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000715}
716
Erik Språng242e22b2015-05-11 10:17:43 +0200717RTCPSender::BuildResult RTCPSender::BuildREMB(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200718 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200719 if (ctx->position + 20 + 4 * remb_ssrcs_.size() >= IP_PACKET_SIZE)
720 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200721
722 // add application layer feedback
723 uint8_t FMT = 15;
Erik Språng242e22b2015-05-11 10:17:43 +0200724 *ctx->AllocateData(1) = 0x80 + FMT;
725 *ctx->AllocateData(1) = 206;
Erik Språng61be2a42015-04-27 13:32:52 +0200726
Erik Språng242e22b2015-05-11 10:17:43 +0200727 *ctx->AllocateData(1) = 0;
728 *ctx->AllocateData(1) = static_cast<uint8_t>(remb_ssrcs_.size() + 4);
Erik Språng61be2a42015-04-27 13:32:52 +0200729
730 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200731 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200732
733 // Remote SSRC must be 0
Erik Språng242e22b2015-05-11 10:17:43 +0200734 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), 0);
Erik Språng61be2a42015-04-27 13:32:52 +0200735
Erik Språng242e22b2015-05-11 10:17:43 +0200736 *ctx->AllocateData(1) = 'R';
737 *ctx->AllocateData(1) = 'E';
738 *ctx->AllocateData(1) = 'M';
739 *ctx->AllocateData(1) = 'B';
Erik Språng61be2a42015-04-27 13:32:52 +0200740
Erik Språng242e22b2015-05-11 10:17:43 +0200741 *ctx->AllocateData(1) = remb_ssrcs_.size();
Erik Språng61be2a42015-04-27 13:32:52 +0200742 // 6 bit Exp
743 // 18 bit mantissa
744 uint8_t brExp = 0;
745 for (uint32_t i = 0; i < 64; i++) {
Erik Språng242e22b2015-05-11 10:17:43 +0200746 if (remb_bitrate_ <= (0x3FFFFu << i)) {
Erik Språng61be2a42015-04-27 13:32:52 +0200747 brExp = i;
748 break;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000749 }
Erik Språng61be2a42015-04-27 13:32:52 +0200750 }
Erik Språng242e22b2015-05-11 10:17:43 +0200751 const uint32_t brMantissa = (remb_bitrate_ >> brExp);
752 *ctx->AllocateData(1) =
753 static_cast<uint8_t>((brExp << 2) + ((brMantissa >> 16) & 0x03));
754 *ctx->AllocateData(1) = static_cast<uint8_t>(brMantissa >> 8);
755 *ctx->AllocateData(1) = static_cast<uint8_t>(brMantissa);
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000756
Erik Språng242e22b2015-05-11 10:17:43 +0200757 for (size_t i = 0; i < remb_ssrcs_.size(); i++)
758 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remb_ssrcs_[i]);
759
760 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
761 "RTCPSender::REMB");
762
763 return BuildResult::kSuccess;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000764}
765
Erik Språng61be2a42015-04-27 13:32:52 +0200766void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
Erik Språng242e22b2015-05-11 10:17:43 +0200767 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
768 tmmbr_send_ = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000769}
770
Erik Språng242e22b2015-05-11 10:17:43 +0200771RTCPSender::BuildResult RTCPSender::BuildTMMBR(RtcpContext* ctx) {
772 if (ctx->feedback_state.module == NULL)
773 return BuildResult::kError;
Erik Språng61be2a42015-04-27 13:32:52 +0200774 // Before sending the TMMBR check the received TMMBN, only an owner is
775 // allowed to raise the bitrate:
776 // * If the sender is an owner of the TMMBN -> send TMMBR
777 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000778
Erik Språng61be2a42015-04-27 13:32:52 +0200779 // get current bounding set from RTCP receiver
780 bool tmmbrOwner = false;
781 // store in candidateSet, allocates one extra slot
Erik Språng242e22b2015-05-11 10:17:43 +0200782 TMMBRSet* candidateSet = tmmbr_help_.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000783
Erik Språng242e22b2015-05-11 10:17:43 +0200784 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
785 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
Erik Språng61be2a42015-04-27 13:32:52 +0200786 // since RTCPreceiver is not doing the reverse we should be fine
787 int32_t lengthOfBoundingSet =
Erik Språng242e22b2015-05-11 10:17:43 +0200788 ctx->feedback_state.module->BoundingSet(tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +0000789
Erik Språng61be2a42015-04-27 13:32:52 +0200790 if (lengthOfBoundingSet > 0) {
791 for (int32_t i = 0; i < lengthOfBoundingSet; i++) {
Erik Språng242e22b2015-05-11 10:17:43 +0200792 if (candidateSet->Tmmbr(i) == tmmbr_send_ &&
793 candidateSet->PacketOH(i) == packet_oh_send_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200794 // do not send the same tuple
Erik Språng242e22b2015-05-11 10:17:43 +0200795 return BuildResult::kAborted;
Erik Språng61be2a42015-04-27 13:32:52 +0200796 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000797 }
Erik Språng61be2a42015-04-27 13:32:52 +0200798 if (!tmmbrOwner) {
799 // use received bounding set as candidate set
800 // add current tuple
Erik Språng242e22b2015-05-11 10:17:43 +0200801 candidateSet->SetEntry(lengthOfBoundingSet, tmmbr_send_, packet_oh_send_,
802 ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200803 int numCandidates = lengthOfBoundingSet + 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000804
Erik Språng61be2a42015-04-27 13:32:52 +0200805 // find bounding set
806 TMMBRSet* boundingSet = NULL;
Erik Språng242e22b2015-05-11 10:17:43 +0200807 int numBoundingSet = tmmbr_help_.FindTMMBRBoundingSet(boundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200808 if (numBoundingSet > 0 || numBoundingSet <= numCandidates)
Erik Språng242e22b2015-05-11 10:17:43 +0200809 tmmbrOwner = tmmbr_help_.IsOwner(ssrc_, numBoundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200810 if (!tmmbrOwner) {
811 // did not enter bounding set, no meaning to send this request
Erik Språng242e22b2015-05-11 10:17:43 +0200812 return BuildResult::kAborted;
Erik Språng61be2a42015-04-27 13:32:52 +0200813 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000814 }
Erik Språng61be2a42015-04-27 13:32:52 +0200815 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000816
Erik Språng242e22b2015-05-11 10:17:43 +0200817 if (tmmbr_send_) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000818 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200819 if (ctx->position + 20 >= IP_PACKET_SIZE)
820 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000821
Erik Språng61be2a42015-04-27 13:32:52 +0200822 // add TMMBR indicator
823 uint8_t FMT = 3;
Erik Språng242e22b2015-05-11 10:17:43 +0200824 *ctx->AllocateData(1) = 0x80 + FMT;
825 *ctx->AllocateData(1) = 205;
Erik Språng61be2a42015-04-27 13:32:52 +0200826
827 // Length of 4
Erik Språng242e22b2015-05-11 10:17:43 +0200828 *ctx->AllocateData(1) = 0;
829 *ctx->AllocateData(1) = 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000830
831 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200832 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000833
Erik Språng61be2a42015-04-27 13:32:52 +0200834 // RFC 5104 4.2.1.2. Semantics
niklase@google.com470e71d2011-07-07 08:21:25 +0000835
836 // SSRC of media source
Erik Språng242e22b2015-05-11 10:17:43 +0200837 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), 0);
niklase@google.com470e71d2011-07-07 08:21:25 +0000838
839 // Additional Feedback Control Information (FCI)
Erik Språng242e22b2015-05-11 10:17:43 +0200840 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remote_ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000841
Erik Språng242e22b2015-05-11 10:17:43 +0200842 uint32_t bitRate = tmmbr_send_ * 1000;
Erik Språng61be2a42015-04-27 13:32:52 +0200843 uint32_t mmbrExp = 0;
844 for (uint32_t i = 0; i < 64; i++) {
845 if (bitRate <= (0x1FFFFu << i)) {
846 mmbrExp = i;
847 break;
848 }
849 }
850 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
851
Erik Språng242e22b2015-05-11 10:17:43 +0200852 *ctx->AllocateData(1) =
Erik Språng61be2a42015-04-27 13:32:52 +0200853 static_cast<uint8_t>((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
Erik Språng242e22b2015-05-11 10:17:43 +0200854 *ctx->AllocateData(1) = static_cast<uint8_t>(mmbrMantissa >> 7);
855 *ctx->AllocateData(1) = static_cast<uint8_t>(
856 (mmbrMantissa << 1) + ((packet_oh_send_ >> 8) & 0x01));
857 *ctx->AllocateData(1) = static_cast<uint8_t>(packet_oh_send_);
Erik Språng61be2a42015-04-27 13:32:52 +0200858 }
Erik Språng242e22b2015-05-11 10:17:43 +0200859 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +0200860}
861
Erik Språng242e22b2015-05-11 10:17:43 +0200862RTCPSender::BuildResult RTCPSender::BuildTMMBN(RtcpContext* ctx) {
863 TMMBRSet* boundingSet = tmmbr_help_.BoundingSetToSend();
Erik Språng61be2a42015-04-27 13:32:52 +0200864 if (boundingSet == NULL)
Erik Språng242e22b2015-05-11 10:17:43 +0200865 return BuildResult::kError;
Erik Språng61be2a42015-04-27 13:32:52 +0200866
867 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200868 if (ctx->position + 12 + boundingSet->lengthOfSet() * 8 >= IP_PACKET_SIZE) {
Erik Språng61be2a42015-04-27 13:32:52 +0200869 LOG(LS_WARNING) << "Failed to build TMMBN.";
Erik Språng242e22b2015-05-11 10:17:43 +0200870 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200871 }
872
873 uint8_t FMT = 4;
874 // add TMMBN indicator
Erik Språng242e22b2015-05-11 10:17:43 +0200875 *ctx->AllocateData(1) = 0x80 + FMT;
876 *ctx->AllocateData(1) = 205;
Erik Språng61be2a42015-04-27 13:32:52 +0200877
878 // Add length later
Erik Språng242e22b2015-05-11 10:17:43 +0200879 int posLength = ctx->position;
880 ctx->AllocateData(2);
Erik Språng61be2a42015-04-27 13:32:52 +0200881
882 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200883 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200884
885 // RFC 5104 4.2.2.2. Semantics
886
887 // SSRC of media source
Erik Språng242e22b2015-05-11 10:17:43 +0200888 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), 0);
Erik Språng61be2a42015-04-27 13:32:52 +0200889
890 // Additional Feedback Control Information (FCI)
891 int numBoundingSet = 0;
892 for (uint32_t n = 0; n < boundingSet->lengthOfSet(); n++) {
893 if (boundingSet->Tmmbr(n) > 0) {
894 uint32_t tmmbrSSRC = boundingSet->Ssrc(n);
Erik Språng242e22b2015-05-11 10:17:43 +0200895 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), tmmbrSSRC);
Erik Språng61be2a42015-04-27 13:32:52 +0200896
897 uint32_t bitRate = boundingSet->Tmmbr(n) * 1000;
898 uint32_t mmbrExp = 0;
899 for (int i = 0; i < 64; i++) {
900 if (bitRate <= (0x1FFFFu << i)) {
901 mmbrExp = i;
andresp@webrtc.org523f9372013-04-11 11:30:39 +0000902 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000903 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +0000904 }
Erik Språng61be2a42015-04-27 13:32:52 +0200905 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
906 uint32_t measuredOH = boundingSet->PacketOH(n);
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000907
Erik Språng242e22b2015-05-11 10:17:43 +0200908 *ctx->AllocateData(1) =
Erik Språng61be2a42015-04-27 13:32:52 +0200909 static_cast<uint8_t>((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
Erik Språng242e22b2015-05-11 10:17:43 +0200910 *ctx->AllocateData(1) = static_cast<uint8_t>(mmbrMantissa >> 7);
911 *ctx->AllocateData(1) = static_cast<uint8_t>((mmbrMantissa << 1) +
912 ((measuredOH >> 8) & 0x01));
913 *ctx->AllocateData(1) = static_cast<uint8_t>(measuredOH);
Erik Språng61be2a42015-04-27 13:32:52 +0200914 numBoundingSet++;
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000915 }
Erik Språng61be2a42015-04-27 13:32:52 +0200916 }
917 uint16_t length = static_cast<uint16_t>(2 + 2 * numBoundingSet);
Erik Språng242e22b2015-05-11 10:17:43 +0200918 ctx->buffer[posLength++] = static_cast<uint8_t>(length >> 8);
919 ctx->buffer[posLength] = static_cast<uint8_t>(length);
920
921 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000922}
923
Erik Språng242e22b2015-05-11 10:17:43 +0200924RTCPSender::BuildResult RTCPSender::BuildAPP(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200925 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200926 if (app_data_ == NULL) {
Erik Språng61be2a42015-04-27 13:32:52 +0200927 LOG(LS_WARNING) << "Failed to build app specific.";
Erik Språng242e22b2015-05-11 10:17:43 +0200928 return BuildResult::kError;
Erik Språng61be2a42015-04-27 13:32:52 +0200929 }
Erik Språng242e22b2015-05-11 10:17:43 +0200930 if (ctx->position + 12 + app_length_ >= IP_PACKET_SIZE) {
Erik Språng61be2a42015-04-27 13:32:52 +0200931 LOG(LS_WARNING) << "Failed to build app specific.";
Erik Språng242e22b2015-05-11 10:17:43 +0200932 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200933 }
Erik Språng242e22b2015-05-11 10:17:43 +0200934 *ctx->AllocateData(1) = 0x80 + app_sub_type_;
Erik Språng61be2a42015-04-27 13:32:52 +0200935
936 // Add APP ID
Erik Språng242e22b2015-05-11 10:17:43 +0200937 *ctx->AllocateData(1) = 204;
Erik Språng61be2a42015-04-27 13:32:52 +0200938
Erik Språng242e22b2015-05-11 10:17:43 +0200939 uint16_t length = (app_length_ >> 2) + 2; // include SSRC and name
940 *ctx->AllocateData(1) = static_cast<uint8_t>(length >> 8);
941 *ctx->AllocateData(1) = static_cast<uint8_t>(length);
Erik Språng61be2a42015-04-27 13:32:52 +0200942
943 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200944 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200945
946 // Add our application name
Erik Språng242e22b2015-05-11 10:17:43 +0200947 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), app_name_);
Erik Språng61be2a42015-04-27 13:32:52 +0200948
949 // Add the data
Erik Språng242e22b2015-05-11 10:17:43 +0200950 memcpy(ctx->AllocateData(app_length_), app_data_.get(), app_length_);
951
952 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +0200953}
954
Erik Språng242e22b2015-05-11 10:17:43 +0200955RTCPSender::BuildResult RTCPSender::BuildNACK(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200956 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200957 if (ctx->position + 16 >= IP_PACKET_SIZE) {
Erik Språng61be2a42015-04-27 13:32:52 +0200958 LOG(LS_WARNING) << "Failed to build NACK.";
Erik Språng242e22b2015-05-11 10:17:43 +0200959 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200960 }
961
Erik Språng242e22b2015-05-11 10:17:43 +0200962 // int size, uint16_t* nack_list
Erik Språng61be2a42015-04-27 13:32:52 +0200963 // add nack list
964 uint8_t FMT = 1;
Erik Språng242e22b2015-05-11 10:17:43 +0200965 *ctx->AllocateData(1) = 0x80 + FMT;
966 *ctx->AllocateData(1) = 205;
Erik Språng61be2a42015-04-27 13:32:52 +0200967
Erik Språng242e22b2015-05-11 10:17:43 +0200968 *ctx->AllocateData(1) = 0;
969 int nack_size_pos_ = ctx->position;
970 *ctx->AllocateData(1) = 3; // setting it to one kNACK signal as default
Erik Språng61be2a42015-04-27 13:32:52 +0200971
972 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200973 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200974
975 // Add the remote SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200976 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200977
978 // Build NACK bitmasks and write them to the RTCP message.
979 // The nack list should be sorted and not contain duplicates if one
980 // wants to build the smallest rtcp nack packet.
981 int numOfNackFields = 0;
982 int maxNackFields =
Erik Språng242e22b2015-05-11 10:17:43 +0200983 std::min<int>(kRtcpMaxNackFields, (IP_PACKET_SIZE - ctx->position) / 4);
Erik Språng61be2a42015-04-27 13:32:52 +0200984 int i = 0;
Erik Språng242e22b2015-05-11 10:17:43 +0200985 while (i < ctx->nack_size && numOfNackFields < maxNackFields) {
986 uint16_t nack = ctx->nack_list[i++];
Erik Språng61be2a42015-04-27 13:32:52 +0200987 uint16_t bitmask = 0;
Erik Språng242e22b2015-05-11 10:17:43 +0200988 while (i < ctx->nack_size) {
989 int shift = static_cast<uint16_t>(ctx->nack_list[i] - nack) - 1;
Erik Språng61be2a42015-04-27 13:32:52 +0200990 if (shift >= 0 && shift <= 15) {
991 bitmask |= (1 << shift);
992 ++i;
993 } else {
994 break;
995 }
996 }
997 // Write the sequence number and the bitmask to the packet.
Erik Språng242e22b2015-05-11 10:17:43 +0200998 assert(ctx->position + 4 < IP_PACKET_SIZE);
999 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2), nack);
1000 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2), bitmask);
Erik Språng61be2a42015-04-27 13:32:52 +02001001 numOfNackFields++;
1002 }
Erik Språng242e22b2015-05-11 10:17:43 +02001003 ctx->buffer[nack_size_pos_] = static_cast<uint8_t>(2 + numOfNackFields);
Erik Språng61be2a42015-04-27 13:32:52 +02001004
Erik Språng242e22b2015-05-11 10:17:43 +02001005 if (i != ctx->nack_size)
Erik Språng61be2a42015-04-27 13:32:52 +02001006 LOG(LS_WARNING) << "Nack list too large for one packet.";
1007
1008 // Report stats.
1009 NACKStringBuilder stringBuilder;
1010 for (int idx = 0; idx < i; ++idx) {
Erik Språng242e22b2015-05-11 10:17:43 +02001011 stringBuilder.PushNACK(ctx->nack_list[idx]);
1012 nack_stats_.ReportRequest(ctx->nack_list[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +02001013 }
Erik Språng61be2a42015-04-27 13:32:52 +02001014 packet_type_counter_.nack_requests = nack_stats_.requests();
1015 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +02001016
1017 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
1018 "RTCPSender::NACK", "nacks",
1019 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
1020 ++packet_type_counter_.nack_packets;
1021 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
1022 ssrc_, packet_type_counter_.nack_packets);
1023
1024 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +02001025}
1026
Erik Språng242e22b2015-05-11 10:17:43 +02001027RTCPSender::BuildResult RTCPSender::BuildBYE(RtcpContext* ctx) {
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001028 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +02001029 if (ctx->position + 8 >= IP_PACKET_SIZE)
1030 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +00001031
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001032 // Add a bye packet
1033 // Number of SSRC + CSRCs.
Erik Språng242e22b2015-05-11 10:17:43 +02001034 *ctx->AllocateData(1) = static_cast<uint8_t>(0x80 + 1 + csrcs_.size());
1035 *ctx->AllocateData(1) = 203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001036
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001037 // length
Erik Språng242e22b2015-05-11 10:17:43 +02001038 *ctx->AllocateData(1) = 0;
1039 *ctx->AllocateData(1) = static_cast<uint8_t>(1 + csrcs_.size());
niklase@google.com470e71d2011-07-07 08:21:25 +00001040
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001041 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +02001042 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +00001043
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001044 // add CSRCs
Erik Språng242e22b2015-05-11 10:17:43 +02001045 for (size_t i = 0; i < csrcs_.size(); i++)
1046 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), csrcs_[i]);
niklase@google.com470e71d2011-07-07 08:21:25 +00001047
Erik Språng242e22b2015-05-11 10:17:43 +02001048 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +00001049}
1050
Erik Språng242e22b2015-05-11 10:17:43 +02001051RTCPSender::BuildResult RTCPSender::BuildReceiverReferenceTime(
1052 RtcpContext* ctx) {
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001053 const int kRrTimeBlockLength = 20;
Erik Språng242e22b2015-05-11 10:17:43 +02001054 if (ctx->position + kRrTimeBlockLength >= IP_PACKET_SIZE)
1055 return BuildResult::kTruncated;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001056
Erik Språng61be2a42015-04-27 13:32:52 +02001057 if (last_xr_rr_.size() >= RTCP_NUMBER_OF_SR)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001058 last_xr_rr_.erase(last_xr_rr_.begin());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001059 last_xr_rr_.insert(std::pair<uint32_t, int64_t>(
Erik Språng242e22b2015-05-11 10:17:43 +02001060 RTCPUtility::MidNtp(ctx->ntp_sec, ctx->ntp_frac),
1061 Clock::NtpToMs(ctx->ntp_sec, ctx->ntp_frac)));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001062
1063 // Add XR header.
Erik Språng242e22b2015-05-11 10:17:43 +02001064 *ctx->AllocateData(1) = 0x80;
1065 *ctx->AllocateData(1) = 207;
1066 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1067 4); // XR packet length.
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001068
1069 // Add our own SSRC.
Erik Språng242e22b2015-05-11 10:17:43 +02001070 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001071
1072 // 0 1 2 3
1073 // 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
1074 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1075 // | BT=4 | reserved | block length = 2 |
1076 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1077 // | NTP timestamp, most significant word |
1078 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1079 // | NTP timestamp, least significant word |
1080 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1081
1082 // Add Receiver Reference Time Report block.
Erik Språng242e22b2015-05-11 10:17:43 +02001083 *ctx->AllocateData(1) = 4; // BT.
1084 *ctx->AllocateData(1) = 0; // Reserved.
1085 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1086 2); // Block length.
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001087
1088 // NTP timestamp.
Erik Språng242e22b2015-05-11 10:17:43 +02001089 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ctx->ntp_sec);
1090 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ctx->ntp_frac);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001091
Erik Språng242e22b2015-05-11 10:17:43 +02001092 return BuildResult::kSuccess;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001093}
1094
Erik Språng242e22b2015-05-11 10:17:43 +02001095RTCPSender::BuildResult RTCPSender::BuildDlrr(RtcpContext* ctx) {
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001096 const int kDlrrBlockLength = 24;
Erik Språng242e22b2015-05-11 10:17:43 +02001097 if (ctx->position + kDlrrBlockLength >= IP_PACKET_SIZE)
1098 return BuildResult::kTruncated;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001099
1100 // Add XR header.
Erik Språng242e22b2015-05-11 10:17:43 +02001101 *ctx->AllocateData(1) = 0x80;
1102 *ctx->AllocateData(1) = 207;
1103 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1104 5); // XR packet length.
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001105
1106 // Add our own SSRC.
Erik Språng242e22b2015-05-11 10:17:43 +02001107 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001108
1109 // 0 1 2 3
1110 // 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
1111 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1112 // | BT=5 | reserved | block length |
1113 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1114 // | SSRC_1 (SSRC of first receiver) | sub-
1115 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1116 // | last RR (LRR) | 1
1117 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1118 // | delay since last RR (DLRR) |
1119 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1120 // | SSRC_2 (SSRC of second receiver) | sub-
1121 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1122 // : ... : 2
1123
1124 // Add DLRR sub block.
Erik Språng242e22b2015-05-11 10:17:43 +02001125 *ctx->AllocateData(1) = 5; // BT.
1126 *ctx->AllocateData(1) = 0; // Reserved.
1127 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1128 3); // Block length.
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001129
1130 // NTP timestamp.
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001131
Erik Språng242e22b2015-05-11 10:17:43 +02001132 const RtcpReceiveTimeInfo& info = ctx->feedback_state.last_xr_rr;
1133 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), info.sourceSSRC);
1134 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), info.lastRR);
1135 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4),
1136 info.delaySinceLastRR);
1137
1138 return BuildResult::kSuccess;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001139}
1140
Erik Språng242e22b2015-05-11 10:17:43 +02001141// TODO(sprang): Add a unit test for this, or remove if the code isn't used.
1142RTCPSender::BuildResult RTCPSender::BuildVoIPMetric(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +02001143 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +02001144 if (ctx->position + 44 >= IP_PACKET_SIZE)
1145 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +00001146
Erik Språng61be2a42015-04-27 13:32:52 +02001147 // Add XR header
Erik Språng242e22b2015-05-11 10:17:43 +02001148 *ctx->AllocateData(1) = 0x80;
1149 *ctx->AllocateData(1) = 207;
niklase@google.com470e71d2011-07-07 08:21:25 +00001150
Erik Språng242e22b2015-05-11 10:17:43 +02001151 uint32_t XRLengthPos = ctx->position;
niklase@google.com470e71d2011-07-07 08:21:25 +00001152
Erik Språng61be2a42015-04-27 13:32:52 +02001153 // handle length later on
Erik Språng242e22b2015-05-11 10:17:43 +02001154 ctx->AllocateData(2);
niklase@google.com470e71d2011-07-07 08:21:25 +00001155
Erik Språng61be2a42015-04-27 13:32:52 +02001156 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +02001157 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +00001158
Erik Språng61be2a42015-04-27 13:32:52 +02001159 // Add a VoIP metrics block
Erik Språng242e22b2015-05-11 10:17:43 +02001160 *ctx->AllocateData(1) = 7;
1161 *ctx->AllocateData(1) = 0;
1162 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2), 8);
niklase@google.com470e71d2011-07-07 08:21:25 +00001163
Erik Språng61be2a42015-04-27 13:32:52 +02001164 // Add the remote SSRC
Erik Språng242e22b2015-05-11 10:17:43 +02001165 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remote_ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +00001166
Erik Språng242e22b2015-05-11 10:17:43 +02001167 *ctx->AllocateData(1) = xr_voip_metric_.lossRate;
1168 *ctx->AllocateData(1) = xr_voip_metric_.discardRate;
1169 *ctx->AllocateData(1) = xr_voip_metric_.burstDensity;
1170 *ctx->AllocateData(1) = xr_voip_metric_.gapDensity;
niklase@google.com470e71d2011-07-07 08:21:25 +00001171
Erik Språng242e22b2015-05-11 10:17:43 +02001172 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1173 xr_voip_metric_.burstDuration);
1174 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1175 xr_voip_metric_.gapDuration);
niklase@google.com470e71d2011-07-07 08:21:25 +00001176
Erik Språng242e22b2015-05-11 10:17:43 +02001177 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1178 xr_voip_metric_.roundTripDelay);
1179 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1180 xr_voip_metric_.endSystemDelay);
niklase@google.com470e71d2011-07-07 08:21:25 +00001181
Erik Språng242e22b2015-05-11 10:17:43 +02001182 *ctx->AllocateData(1) = xr_voip_metric_.signalLevel;
1183 *ctx->AllocateData(1) = xr_voip_metric_.noiseLevel;
1184 *ctx->AllocateData(1) = xr_voip_metric_.RERL;
1185 *ctx->AllocateData(1) = xr_voip_metric_.Gmin;
niklase@google.com470e71d2011-07-07 08:21:25 +00001186
Erik Språng242e22b2015-05-11 10:17:43 +02001187 *ctx->AllocateData(1) = xr_voip_metric_.Rfactor;
1188 *ctx->AllocateData(1) = xr_voip_metric_.extRfactor;
1189 *ctx->AllocateData(1) = xr_voip_metric_.MOSLQ;
1190 *ctx->AllocateData(1) = xr_voip_metric_.MOSCQ;
niklase@google.com470e71d2011-07-07 08:21:25 +00001191
Erik Språng242e22b2015-05-11 10:17:43 +02001192 *ctx->AllocateData(1) = xr_voip_metric_.RXconfig;
1193 *ctx->AllocateData(1) = 0; // reserved
niklase@google.com470e71d2011-07-07 08:21:25 +00001194
Erik Språng242e22b2015-05-11 10:17:43 +02001195 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1196 xr_voip_metric_.JBnominal);
1197 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1198 xr_voip_metric_.JBmax);
1199 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1200 xr_voip_metric_.JBabsMax);
niklase@google.com470e71d2011-07-07 08:21:25 +00001201
Erik Språng242e22b2015-05-11 10:17:43 +02001202 ByteWriter<uint16_t>::WriteBigEndian(&ctx->buffer[XRLengthPos], 10);
1203
1204 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +00001205}
1206
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001207int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +02001208 RTCPPacketType packetType,
1209 int32_t nack_size,
1210 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001211 bool repeat,
1212 uint64_t pictureID) {
Erik Språng242e22b2015-05-11 10:17:43 +02001213 return SendCompoundRTCP(
1214 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
1215 nack_size, nack_list, repeat, pictureID);
1216}
1217
1218int32_t RTCPSender::SendCompoundRTCP(
1219 const FeedbackState& feedback_state,
1220 const std::set<RTCPPacketType>& packetTypes,
1221 int32_t nack_size,
1222 const uint16_t* nack_list,
1223 bool repeat,
1224 uint64_t pictureID) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001225 {
Erik Språng242e22b2015-05-11 10:17:43 +02001226 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1227 if (method_ == kRtcpOff) {
Erik Språng61be2a42015-04-27 13:32:52 +02001228 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
1229 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +00001230 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001231 }
1232 uint8_t rtcp_buffer[IP_PACKET_SIZE];
Erik Språng242e22b2015-05-11 10:17:43 +02001233 int rtcp_length =
1234 PrepareRTCP(feedback_state, packetTypes, nack_size, nack_list, repeat,
1235 pictureID, rtcp_buffer, IP_PACKET_SIZE);
Erik Språng61be2a42015-04-27 13:32:52 +02001236
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001237 // Sanity don't send empty packets.
Erik Språng242e22b2015-05-11 10:17:43 +02001238 if (rtcp_length <= 0)
1239 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +02001240
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00001241 return SendToNetwork(rtcp_buffer, static_cast<size_t>(rtcp_length));
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001242}
1243
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001244int RTCPSender::PrepareRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +02001245 const std::set<RTCPPacketType>& packetTypes,
1246 int32_t nack_size,
1247 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001248 bool repeat,
1249 uint64_t pictureID,
1250 uint8_t* rtcp_buffer,
1251 int buffer_size) {
Erik Språng242e22b2015-05-11 10:17:43 +02001252 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001253
Erik Språng242e22b2015-05-11 10:17:43 +02001254 RtcpContext context(feedback_state, nack_size, nack_list, repeat, pictureID,
1255 rtcp_buffer, buffer_size);
1256
1257 // Add all flags as volatile. Non volatile entries will not be overwritten
1258 // and all new volatile flags added will be consumed by the end of this call.
1259 SetFlags(packetTypes, true);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001260
Erik Språng61be2a42015-04-27 13:32:52 +02001261 if (packet_type_counter_.first_packet_time_ms == -1)
Erik Språng242e22b2015-05-11 10:17:43 +02001262 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språng61be2a42015-04-27 13:32:52 +02001263
Erik Språng242e22b2015-05-11 10:17:43 +02001264 bool generate_report;
1265 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
1266 // Report type already explicitly set, don't automatically populate.
1267 generate_report = true;
1268 DCHECK(ConsumeFlag(kRtcpReport) == false);
1269 } else {
1270 generate_report =
1271 (ConsumeFlag(kRtcpReport) && method_ == kRtcpNonCompound) ||
1272 method_ == kRtcpCompound;
1273 if (generate_report)
1274 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +00001275 }
1276
Erik Språng0ea42d32015-06-25 14:46:16 +02001277 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
Erik Språng242e22b2015-05-11 10:17:43 +02001278 SetFlag(kRtcpSdes, true);
1279
1280 // We need to send our NTP even if we haven't received any reports.
1281 clock_->CurrentNtp(context.ntp_sec, context.ntp_frac);
1282
1283 if (generate_report) {
1284 if (!sending_ && xr_send_receiver_reference_time_enabled_)
1285 SetFlag(kRtcpXrReceiverReferenceTime, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001286 if (feedback_state.has_last_xr_rr)
Erik Språng242e22b2015-05-11 10:17:43 +02001287 SetFlag(kRtcpXrDlrrReportBlock, true);
1288
1289 // generate next time to send an RTCP report
Erik Språng61be2a42015-04-27 13:32:52 +02001290 // seeded from RTP constructor
1291 int32_t random = rand() % 1000;
1292 int32_t timeToNext = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001293
Erik Språng242e22b2015-05-11 10:17:43 +02001294 if (audio_) {
Erik Språng61be2a42015-04-27 13:32:52 +02001295 timeToNext = (RTCP_INTERVAL_AUDIO_MS / 2) +
1296 (RTCP_INTERVAL_AUDIO_MS * random / 1000);
1297 } else {
1298 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
Erik Språng242e22b2015-05-11 10:17:43 +02001299 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +02001300 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
1301 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
1302 if (send_bitrate_kbit != 0)
1303 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001304 }
Erik Språng61be2a42015-04-27 13:32:52 +02001305 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
1306 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
1307 timeToNext = (minIntervalMs / 2) + (minIntervalMs * random / 1000);
1308 }
Erik Språng242e22b2015-05-11 10:17:43 +02001309 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001310
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001311 StatisticianMap statisticians =
1312 receive_statistics_->GetActiveStatisticians();
1313 if (!statisticians.empty()) {
Erik Språng61be2a42015-04-27 13:32:52 +02001314 for (auto it = statisticians.begin(); it != statisticians.end(); ++it) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001315 RTCPReportBlock report_block;
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001316 if (PrepareReport(feedback_state, it->first, it->second,
1317 &report_block)) {
1318 AddReportBlock(report_block);
Erik Språng61be2a42015-04-27 13:32:52 +02001319 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001320 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001321 }
1322 }
1323
Erik Språng242e22b2015-05-11 10:17:43 +02001324 auto it = report_flags_.begin();
1325 while (it != report_flags_.end()) {
1326 auto builder = builders_.find(it->type);
1327 DCHECK(builder != builders_.end());
1328 if (it->is_volatile) {
1329 report_flags_.erase(it++);
1330 } else {
1331 ++it;
Erik Språng61be2a42015-04-27 13:32:52 +02001332 }
Erik Språng242e22b2015-05-11 10:17:43 +02001333
1334 uint32_t start_position = context.position;
Erik Språng0ea42d32015-06-25 14:46:16 +02001335 BuildResult result = (this->*(builder->second))(&context);
Erik Språng242e22b2015-05-11 10:17:43 +02001336 switch (result) {
1337 case BuildResult::kError:
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001338 return -1;
Erik Språng242e22b2015-05-11 10:17:43 +02001339 case BuildResult::kTruncated:
1340 return context.position;
1341 case BuildResult::kAborted:
1342 context.position = start_position;
1343 FALLTHROUGH();
1344 case BuildResult::kSuccess:
1345 continue;
Erik Språng61be2a42015-04-27 13:32:52 +02001346 default:
Erik Språng242e22b2015-05-11 10:17:43 +02001347 abort();
Erik Språng61be2a42015-04-27 13:32:52 +02001348 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001349 }
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001350
1351 if (packet_type_counter_observer_ != NULL) {
1352 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
Erik Språng242e22b2015-05-11 10:17:43 +02001353 remote_ssrc_, packet_type_counter_);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001354 }
1355
Erik Språng242e22b2015-05-11 10:17:43 +02001356 DCHECK(AllVolatileFlagsConsumed());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001357
Erik Språng242e22b2015-05-11 10:17:43 +02001358 return context.position;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001359}
1360
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001361bool RTCPSender::PrepareReport(const FeedbackState& feedback_state,
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001362 uint32_t ssrc,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001363 StreamStatistician* statistician,
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001364 RTCPReportBlock* report_block) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001365 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +00001366 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001367 if (!statistician->GetStatistics(&stats, true))
1368 return false;
1369 report_block->fractionLost = stats.fraction_lost;
1370 report_block->cumulativeLost = stats.cumulative_lost;
1371 report_block->extendedHighSeqNum =
1372 stats.extended_max_sequence_number;
1373 report_block->jitter = stats.jitter;
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001374 report_block->remoteSSRC = ssrc;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001375
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001376 // TODO(sprang): Do we really need separate time stamps for each report?
1377 // Get our NTP as late as possible to avoid a race.
1378 uint32_t ntp_secs;
1379 uint32_t ntp_frac;
1380 clock_->CurrentNtp(ntp_secs, ntp_frac);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001381
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001382 // Delay since last received report.
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001383 uint32_t delaySinceLastReceivedSR = 0;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001384 if ((feedback_state.last_rr_ntp_secs != 0) ||
1385 (feedback_state.last_rr_ntp_frac != 0)) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001386 // Get the 16 lowest bits of seconds and the 16 highest bits of fractions.
1387 uint32_t now = ntp_secs & 0x0000FFFF;
Erik Språng61be2a42015-04-27 13:32:52 +02001388 now <<= 16;
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001389 now += (ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001390
Erik Språng61be2a42015-04-27 13:32:52 +02001391 uint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
1392 receiveTime <<= 16;
1393 receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001394
1395 delaySinceLastReceivedSR = now-receiveTime;
1396 }
1397 report_block->delaySinceLastSR = delaySinceLastReceivedSR;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001398 report_block->lastSR = feedback_state.remote_sr;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001399 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +00001400}
1401
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001402int32_t RTCPSender::SendToNetwork(const uint8_t* dataBuffer, size_t length) {
Erik Språng242e22b2015-05-11 10:17:43 +02001403 CriticalSectionScoped lock(critical_section_transport_.get());
1404 if (cbTransport_) {
1405 if (cbTransport_->SendRTCPPacket(id_, dataBuffer, length) > 0)
Erik Språng61be2a42015-04-27 13:32:52 +02001406 return 0;
1407 }
1408 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001409}
1410
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001411void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
1412 assert(csrcs.size() <= kRtpCsrcSize);
Erik Språng242e22b2015-05-11 10:17:43 +02001413 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001414 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +00001415}
1416
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001417int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
1418 uint32_t name,
1419 const uint8_t* data,
1420 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +02001421 if (length % 4 != 0) {
1422 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
1423 return -1;
1424 }
Erik Språng242e22b2015-05-11 10:17:43 +02001425 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +00001426
Erik Språng242e22b2015-05-11 10:17:43 +02001427 SetFlag(kRtcpApp, true);
1428 app_sub_type_ = subType;
1429 app_name_ = name;
1430 app_data_.reset(new uint8_t[length]);
1431 app_length_ = length;
1432 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +02001433 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001434}
1435
Erik Språng61be2a42015-04-27 13:32:52 +02001436int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
Erik Språng242e22b2015-05-11 10:17:43 +02001437 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1438 memcpy(&xr_voip_metric_, VoIPMetric, sizeof(RTCPVoIPMetric));
niklase@google.com470e71d2011-07-07 08:21:25 +00001439
Erik Språng242e22b2015-05-11 10:17:43 +02001440 SetFlag(kRtcpXrVoipMetric, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001441 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001442}
1443
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001444void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +02001445 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1446 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001447}
1448
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00001449bool RTCPSender::RtcpXrReceiverReferenceTime() const {
Erik Språng242e22b2015-05-11 10:17:43 +02001450 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1451 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00001452}
1453
niklase@google.com470e71d2011-07-07 08:21:25 +00001454// no callbacks allowed inside this function
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001455int32_t RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
1456 uint32_t maxBitrateKbit) {
Erik Språng242e22b2015-05-11 10:17:43 +02001457 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +00001458
Erik Språng242e22b2015-05-11 10:17:43 +02001459 if (0 == tmmbr_help_.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit)) {
1460 SetFlag(kRtcpTmmbn, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001461 return 0;
1462 }
1463 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001464}
Erik Språng61be2a42015-04-27 13:32:52 +02001465
Erik Språng242e22b2015-05-11 10:17:43 +02001466void RTCPSender::SetFlag(RTCPPacketType type, bool is_volatile) {
1467 report_flags_.insert(ReportFlag(type, is_volatile));
1468}
1469
1470void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
1471 bool is_volatile) {
1472 for (RTCPPacketType type : types)
1473 SetFlag(type, is_volatile);
1474}
1475
1476bool RTCPSender::IsFlagPresent(RTCPPacketType type) const {
1477 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
1478}
1479
1480bool RTCPSender::ConsumeFlag(RTCPPacketType type, bool forced) {
1481 auto it = report_flags_.find(ReportFlag(type, false));
1482 if (it == report_flags_.end())
1483 return false;
1484 if (it->is_volatile || forced)
1485 report_flags_.erase((it));
1486 return true;
1487}
1488
1489bool RTCPSender::AllVolatileFlagsConsumed() const {
1490 for (const ReportFlag& flag : report_flags_) {
1491 if (flag.is_volatile)
1492 return false;
1493 }
1494 return true;
1495}
1496
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001497} // namespace webrtc