blob: d15de162d9607f06cabcaa4e31372dc1e4b68ce0 [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),
93 jitter_transmission_offset(0),
94 position(0) {}
95
96 uint8_t* AllocateData(uint32_t bytes) {
97 DCHECK_LE(position + bytes, buffer_size);
98 uint8_t* ptr = &buffer[position];
99 position += bytes;
100 return ptr;
101 }
102
103 const FeedbackState& feedback_state;
104 int32_t nack_size;
105 const uint16_t* nack_list;
106 bool repeat;
107 uint64_t picture_id;
108 uint8_t* buffer;
109 uint32_t buffer_size;
110 uint32_t ntp_sec;
111 uint32_t ntp_frac;
112 uint32_t jitter_transmission_offset;
113 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 }
125
126 private:
127 RtcpContext* const context_;
128};
129
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000130RTCPSender::RTCPSender(
131 int32_t id,
132 bool audio,
133 Clock* clock,
134 ReceiveStatistics* receive_statistics,
135 RtcpPacketTypeCounterObserver* packet_type_counter_observer)
Erik Språng242e22b2015-05-11 10:17:43 +0200136 : id_(id),
137 audio_(audio),
138 clock_(clock),
139 method_(kRtcpOff),
140 critical_section_transport_(
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000141 CriticalSectionWrapper::CreateCriticalSection()),
Erik Språng242e22b2015-05-11 10:17:43 +0200142 cbTransport_(nullptr),
niklase@google.com470e71d2011-07-07 08:21:25 +0000143
Erik Språng242e22b2015-05-11 10:17:43 +0200144 critical_section_rtcp_sender_(
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000145 CriticalSectionWrapper::CreateCriticalSection()),
Erik Språng242e22b2015-05-11 10:17:43 +0200146 using_nack_(false),
147 sending_(false),
148 remb_enabled_(false),
149 extended_jitter_report_enabled_(false),
150 next_time_to_send_rtcp_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000151 start_timestamp_(0),
152 last_rtp_timestamp_(0),
153 last_frame_capture_time_ms_(-1),
Erik Språng242e22b2015-05-11 10:17:43 +0200154 ssrc_(0),
155 remote_ssrc_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000156 receive_statistics_(receive_statistics),
niklase@google.com470e71d2011-07-07 08:21:25 +0000157
Erik Språng242e22b2015-05-11 10:17:43 +0200158 sequence_number_fir_(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000159
Erik Språng242e22b2015-05-11 10:17:43 +0200160 remb_bitrate_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000161
Erik Språng242e22b2015-05-11 10:17:43 +0200162 tmmbr_help_(),
163 tmmbr_send_(0),
164 packet_oh_send_(0),
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000165
Erik Språng242e22b2015-05-11 10:17:43 +0200166 app_sub_type_(0),
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200167 app_name_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200168 app_data_(nullptr),
169 app_length_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000170
Erik Språng242e22b2015-05-11 10:17:43 +0200171 xr_send_receiver_reference_time_enabled_(false),
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000172 packet_type_counter_observer_(packet_type_counter_observer) {
Erik Språng242e22b2015-05-11 10:17:43 +0200173 memset(last_send_report_, 0, sizeof(last_send_report_));
174 memset(last_rtcp_time_, 0, sizeof(last_rtcp_time_));
175
176 builders_[kRtcpSr] = &RTCPSender::BuildSR;
177 builders_[kRtcpRr] = &RTCPSender::BuildRR;
Erik Språng0ea42d32015-06-25 14:46:16 +0200178 builders_[kRtcpSdes] = &RTCPSender::BuildSDES;
Erik Språng242e22b2015-05-11 10:17:43 +0200179 builders_[kRtcpTransmissionTimeOffset] =
180 &RTCPSender::BuildExtendedJitterReport;
181 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
Erik Språng61be2a42015-04-27 13:32:52 +0200283bool RTCPSender::IJ() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200284 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
285 return extended_jitter_report_enabled_;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000286}
287
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000288void RTCPSender::SetIJStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200289 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
290 extended_jitter_report_enabled_ = enable;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000291}
292
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000293void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
Erik Språng242e22b2015-05-11 10:17:43 +0200294 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000295 start_timestamp_ = start_timestamp;
296}
297
298void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
299 int64_t capture_time_ms) {
Erik Språng242e22b2015-05-11 10:17:43 +0200300 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000301 last_rtp_timestamp_ = rtp_timestamp;
302 if (capture_time_ms < 0) {
303 // We don't currently get a capture time from VoiceEngine.
Erik Språng242e22b2015-05-11 10:17:43 +0200304 last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000305 } else {
306 last_frame_capture_time_ms_ = capture_time_ms;
307 }
308}
309
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000310void RTCPSender::SetSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200311 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000312
Erik Språng242e22b2015-05-11 10:17:43 +0200313 if (ssrc_ != 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200314 // not first SetSSRC, probably due to a collision
315 // schedule a new RTCP report
316 // make sure that we send a RTP packet
Erik Språng242e22b2015-05-11 10:17:43 +0200317 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
Erik Språng61be2a42015-04-27 13:32:52 +0200318 }
Erik Språng242e22b2015-05-11 10:17:43 +0200319 ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000320}
321
Erik Språng61be2a42015-04-27 13:32:52 +0200322void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200323 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
324 remote_ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000325}
326
Peter Boström9ba52f82015-06-01 14:12:28 +0200327int32_t RTCPSender::SetCNAME(const char* c_name) {
328 if (!c_name)
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000329 return -1;
330
Peter Boström9ba52f82015-06-01 14:12:28 +0200331 DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
Erik Språng242e22b2015-05-11 10:17:43 +0200332 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200333 cname_ = c_name;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000334 return 0;
335}
336
Erik Språng0ea42d32015-06-25 14:46:16 +0200337int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC, const char* c_name) {
338 assert(c_name);
339 DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
Erik Språng242e22b2015-05-11 10:17:43 +0200340 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200341 if (csrc_cnames_.size() >= kRtpCsrcSize)
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000342 return -1;
Erik Språng0ea42d32015-06-25 14:46:16 +0200343
344 csrc_cnames_[SSRC] = c_name;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000345 return 0;
346}
347
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000348int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
Erik Språng242e22b2015-05-11 10:17:43 +0200349 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200350 auto it = csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000351
Erik Språng242e22b2015-05-11 10:17:43 +0200352 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000353 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200354
Erik Språng242e22b2015-05-11 10:17:43 +0200355 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000356 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000357}
358
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000359bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
niklase@google.com470e71d2011-07-07 08:21:25 +0000360/*
361 For audio we use a fix 5 sec interval
362
363 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000364 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
365 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000366
367
368From RFC 3550
369
370 MAX RTCP BW is 5% if the session BW
371 A send report is approximately 65 bytes inc CNAME
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000372 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000373
374 The RECOMMENDED value for the reduced minimum in seconds is 360
375 divided by the session bandwidth in kilobits/second. This minimum
376 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
377
378 If the participant has not yet sent an RTCP packet (the variable
379 initial is true), the constant Tmin is set to 2.5 seconds, else it
380 is set to 5 seconds.
381
382 The interval between RTCP packets is varied randomly over the
383 range [0.5,1.5] times the calculated interval to avoid unintended
384 synchronization of all participants
385
386 if we send
387 If the participant is a sender (we_sent true), the constant C is
388 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
389 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
390 number of senders.
391
392 if we receive only
393 If we_sent is not true, the constant C is set
394 to the average RTCP packet size divided by 75% of the RTCP
395 bandwidth. The constant n is set to the number of receivers
396 (members - senders). If the number of senders is greater than
397 25%, senders and receivers are treated together.
398
399 reconsideration NOT required for peer-to-peer
400 "timer reconsideration" is
401 employed. This algorithm implements a simple back-off mechanism
402 which causes users to hold back RTCP packet transmission if the
403 group sizes are increasing.
404
405 n = number of members
406 C = avg_size/(rtcpBW/4)
407
408 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
409
410 4. The calculated interval T is set to a number uniformly distributed
411 between 0.5 and 1.5 times the deterministic calculated interval.
412
413 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
414 for the fact that the timer reconsideration algorithm converges to
415 a value of the RTCP bandwidth below the intended average
416*/
417
Erik Språng242e22b2015-05-11 10:17:43 +0200418 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000419
Erik Språng242e22b2015-05-11 10:17:43 +0200420 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
xians@webrtc.org8738d272011-11-25 13:43:53 +0000421
Erik Språng242e22b2015-05-11 10:17:43 +0200422 if (method_ == kRtcpOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000423 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000424
Erik Språng242e22b2015-05-11 10:17:43 +0200425 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200426 // for video key-frames we want to send the RTCP before the large key-frame
427 // if we have a 100 ms margin
428 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
429 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000430
Erik Språng242e22b2015-05-11 10:17:43 +0200431 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200432 return true;
433 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200434 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200435 // wrap
436 return true;
437 }
438 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000439}
440
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000441int64_t RTCPSender::SendTimeOfSendReport(uint32_t sendReport) {
Erik Språng242e22b2015-05-11 10:17:43 +0200442 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000443
Erik Språng61be2a42015-04-27 13:32:52 +0200444 // This is only saved when we are the sender
Erik Språng242e22b2015-05-11 10:17:43 +0200445 if ((last_send_report_[0] == 0) || (sendReport == 0)) {
Erik Språng61be2a42015-04-27 13:32:52 +0200446 return 0; // will be ignored
447 } else {
448 for (int i = 0; i < RTCP_NUMBER_OF_SR; ++i) {
Erik Språng242e22b2015-05-11 10:17:43 +0200449 if (last_send_report_[i] == sendReport)
450 return last_rtcp_time_[i];
niklase@google.com470e71d2011-07-07 08:21:25 +0000451 }
Erik Språng61be2a42015-04-27 13:32:52 +0200452 }
453 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000454}
455
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000456bool RTCPSender::SendTimeOfXrRrReport(uint32_t mid_ntp,
457 int64_t* time_ms) const {
Erik Språng242e22b2015-05-11 10:17:43 +0200458 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000459
460 if (last_xr_rr_.empty()) {
461 return false;
462 }
463 std::map<uint32_t, int64_t>::const_iterator it = last_xr_rr_.find(mid_ntp);
464 if (it == last_xr_rr_.end()) {
465 return false;
466 }
467 *time_ms = it->second;
468 return true;
469}
470
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200471int32_t RTCPSender::AddReportBlock(const RTCPReportBlock& report_block) {
472 if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000473 LOG(LS_WARNING) << "Too many report blocks.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000474 return -1;
475 }
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200476 rtcp::ReportBlock* block = &report_blocks_[report_block.remoteSSRC];
477 block->To(report_block.remoteSSRC);
478 block->WithFractionLost(report_block.fractionLost);
479 block->WithCumulativeLost(report_block.cumulativeLost);
480 block->WithExtHighestSeqNum(report_block.extendedHighSeqNum);
481 block->WithJitter(report_block.jitter);
482 block->WithLastSr(report_block.lastSR);
483 block->WithDelayLastSr(report_block.delaySinceLastSR);
484
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000485 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000486}
487
Erik Språng242e22b2015-05-11 10:17:43 +0200488RTCPSender::BuildResult RTCPSender::BuildSR(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200489 for (int i = (RTCP_NUMBER_OF_SR - 2); i >= 0; i--) {
490 // shift old
Erik Språng242e22b2015-05-11 10:17:43 +0200491 last_send_report_[i + 1] = last_send_report_[i];
492 last_rtcp_time_[i + 1] = last_rtcp_time_[i];
Erik Språng61be2a42015-04-27 13:32:52 +0200493 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000494
Erik Språng242e22b2015-05-11 10:17:43 +0200495 last_rtcp_time_[0] = Clock::NtpToMs(ctx->ntp_sec, ctx->ntp_frac);
496 last_send_report_[0] = (ctx->ntp_sec << 16) + (ctx->ntp_frac >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000497
Erik Språng61be2a42015-04-27 13:32:52 +0200498 // The timestamp of this RTCP packet should be estimated as the timestamp of
499 // the frame being captured at this moment. We are calculating that
500 // timestamp as the last frame's timestamp + the time since the last frame
501 // was captured.
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200502 uint32_t rtp_timestamp =
503 start_timestamp_ + last_rtp_timestamp_ +
504 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) *
505 (ctx->feedback_state.frequency_hz / 1000);
niklase@google.com470e71d2011-07-07 08:21:25 +0000506
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200507 rtcp::SenderReport report;
508 report.From(ssrc_);
509 report.WithNtpSec(ctx->ntp_sec);
510 report.WithNtpFrac(ctx->ntp_frac);
511 report.WithRtpTimestamp(rtp_timestamp);
512 report.WithPacketCount(ctx->feedback_state.packets_sent);
513 report.WithOctetCount(ctx->feedback_state.media_bytes_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000514
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200515 for (auto it : report_blocks_)
516 report.WithReportBlock(it.second);
niklase@google.com470e71d2011-07-07 08:21:25 +0000517
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200518 PacketBuiltCallback callback(ctx);
519 if (!report.BuildExternalBuffer(&ctx->buffer[ctx->position],
520 ctx->buffer_size - ctx->position,
521 &callback)) {
522 return BuildResult::kTruncated;
Erik Språng242e22b2015-05-11 10:17:43 +0200523 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000524
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200525 report_blocks_.clear();
Erik Språng242e22b2015-05-11 10:17:43 +0200526 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000527}
528
Erik Språng0ea42d32015-06-25 14:46:16 +0200529RTCPSender::BuildResult RTCPSender::BuildSDES(RtcpContext* ctx) {
530 size_t length_cname = cname_.length();
531 CHECK_LT(length_cname, static_cast<size_t>(RTCP_CNAME_SIZE));
niklase@google.com470e71d2011-07-07 08:21:25 +0000532
Erik Språng0ea42d32015-06-25 14:46:16 +0200533 rtcp::Sdes sdes;
534 sdes.WithCName(ssrc_, cname_);
535
536 for (const auto it : csrc_cnames_)
537 sdes.WithCName(it.first, it.second);
538
539 PacketBuiltCallback callback(ctx);
540 if (!sdes.BuildExternalBuffer(&ctx->buffer[ctx->position],
541 ctx->buffer_size - ctx->position, &callback)) {
Erik Språng242e22b2015-05-11 10:17:43 +0200542 return BuildResult::kTruncated;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000543 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000544
Erik Språng242e22b2015-05-11 10:17:43 +0200545 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000546}
547
Erik Språng242e22b2015-05-11 10:17:43 +0200548RTCPSender::BuildResult RTCPSender::BuildRR(RtcpContext* ctx) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200549 rtcp::ReceiverReport report;
550 report.From(ssrc_);
551 for (auto it : report_blocks_)
552 report.WithReportBlock(it.second);
553
554 PacketBuiltCallback callback(ctx);
555 if (!report.BuildExternalBuffer(&ctx->buffer[ctx->position],
556 ctx->buffer_size - ctx->position,
557 &callback)) {
Erik Språng242e22b2015-05-11 10:17:43 +0200558 return BuildResult::kTruncated;
Erik Språng242e22b2015-05-11 10:17:43 +0200559 }
Erik Språng61be2a42015-04-27 13:32:52 +0200560
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200561 report_blocks_.clear();
Erik Språng242e22b2015-05-11 10:17:43 +0200562
563 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000564}
565
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000566// From RFC 5450: Transmission Time Offsets in RTP Streams.
567// 0 1 2 3
568// 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
569// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
570// hdr |V=2|P| RC | PT=IJ=195 | length |
571// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
572// | inter-arrival jitter |
573// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
574// . .
575// . .
576// . .
577// | inter-arrival jitter |
578// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
579//
580// If present, this RTCP packet must be placed after a receiver report
581// (inside a compound RTCP packet), and MUST have the same value for RC
582// (reception report count) as the receiver report.
583
Erik Språng242e22b2015-05-11 10:17:43 +0200584RTCPSender::BuildResult RTCPSender::BuildExtendedJitterReport(
585 RtcpContext* ctx) {
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000586 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200587 if (ctx->position + 8 >= IP_PACKET_SIZE)
588 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200589
590 // add picture loss indicator
591 uint8_t RC = 1;
Erik Språng242e22b2015-05-11 10:17:43 +0200592 *ctx->AllocateData(1) = 0x80 + RC;
593 *ctx->AllocateData(1) = 195;
Erik Språng61be2a42015-04-27 13:32:52 +0200594
595 // Used fixed length of 2
Erik Språng242e22b2015-05-11 10:17:43 +0200596 *ctx->AllocateData(1) = 0;
597 *ctx->AllocateData(1) = 1;
Erik Språng61be2a42015-04-27 13:32:52 +0200598
599 // Add inter-arrival jitter
Erik Språng242e22b2015-05-11 10:17:43 +0200600 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4),
601 ctx->jitter_transmission_offset);
602 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +0200603}
604
Erik Språng242e22b2015-05-11 10:17:43 +0200605RTCPSender::BuildResult RTCPSender::BuildPLI(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200606 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200607 if (ctx->position + 12 >= IP_PACKET_SIZE)
608 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200609
610 // add picture loss indicator
611 uint8_t FMT = 1;
Erik Språng242e22b2015-05-11 10:17:43 +0200612 *ctx->AllocateData(1) = 0x80 + FMT;
613 *ctx->AllocateData(1) = 206;
Erik Språng61be2a42015-04-27 13:32:52 +0200614
615 // Used fixed length of 2
Erik Språng242e22b2015-05-11 10:17:43 +0200616 *ctx->AllocateData(1) = 0;
617 *ctx->AllocateData(1) = 2;
Erik Språng61be2a42015-04-27 13:32:52 +0200618
619 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200620 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200621
622 // Add the remote SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200623 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remote_ssrc_);
624
625 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
626 "RTCPSender::PLI");
627 ++packet_type_counter_.pli_packets;
628 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
629 ssrc_, packet_type_counter_.pli_packets);
630
631 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +0200632}
633
Erik Språng242e22b2015-05-11 10:17:43 +0200634RTCPSender::BuildResult RTCPSender::BuildFIR(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200635 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200636 if (ctx->position + 20 >= IP_PACKET_SIZE)
637 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200638
Erik Språng242e22b2015-05-11 10:17:43 +0200639 if (!ctx->repeat)
640 sequence_number_fir_++; // do not increase if repetition
niklase@google.com470e71d2011-07-07 08:21:25 +0000641
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000642 // add full intra request indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000643 uint8_t FMT = 4;
Erik Språng242e22b2015-05-11 10:17:43 +0200644 *ctx->AllocateData(1) = 0x80 + FMT;
645 *ctx->AllocateData(1) = 206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000646
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000647 //Length of 4
Erik Språng242e22b2015-05-11 10:17:43 +0200648 *ctx->AllocateData(1) = 0;
649 *ctx->AllocateData(1) = 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000650
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000651 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200652 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000653
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000654 // RFC 5104 4.3.1.2. Semantics
655 // SSRC of media source
Erik Språng242e22b2015-05-11 10:17:43 +0200656 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), 0);
niklase@google.com470e71d2011-07-07 08:21:25 +0000657
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000658 // Additional Feedback Control Information (FCI)
Erik Språng242e22b2015-05-11 10:17:43 +0200659 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remote_ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000660
Erik Språng242e22b2015-05-11 10:17:43 +0200661 *ctx->AllocateData(1) = sequence_number_fir_;
662 *ctx->AllocateData(1) = 0;
663 *ctx->AllocateData(1) = 0;
664 *ctx->AllocateData(1) = 0;
665
666 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
667 "RTCPSender::FIR");
668 ++packet_type_counter_.fir_packets;
669 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
670 ssrc_, packet_type_counter_.fir_packets);
671
672 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000673}
674
675/*
676 0 1 2 3
677 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
678 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
679 | First | Number | PictureID |
680 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
681*/
Erik Språng242e22b2015-05-11 10:17:43 +0200682RTCPSender::BuildResult RTCPSender::BuildSLI(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200683 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200684 if (ctx->position + 16 >= IP_PACKET_SIZE)
685 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000686
Erik Språng61be2a42015-04-27 13:32:52 +0200687 // add slice loss indicator
688 uint8_t FMT = 2;
Erik Språng242e22b2015-05-11 10:17:43 +0200689 *ctx->AllocateData(1) = 0x80 + FMT;
690 *ctx->AllocateData(1) = 206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000691
Erik Språng61be2a42015-04-27 13:32:52 +0200692 // Used fixed length of 3
Erik Språng242e22b2015-05-11 10:17:43 +0200693 *ctx->AllocateData(1) = 0;
694 *ctx->AllocateData(1) = 3;
niklase@google.com470e71d2011-07-07 08:21:25 +0000695
Erik Språng61be2a42015-04-27 13:32:52 +0200696 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200697 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000698
Erik Språng61be2a42015-04-27 13:32:52 +0200699 // Add the remote SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200700 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200701
702 // Add first, number & picture ID 6 bits
703 // first = 0, 13 - bits
704 // number = 0x1fff, 13 - bits only ones for now
Erik Språng242e22b2015-05-11 10:17:43 +0200705 uint32_t sliField = (0x1fff << 6) + (0x3f & ctx->picture_id);
706 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), sliField);
707
708 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000709}
710
711/*
712 0 1 2 3
713 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
714 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
715 | PB |0| Payload Type| Native RPSI bit string |
716 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
717 | defined per codec ... | Padding (0) |
718 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
719*/
720/*
721* Note: not generic made for VP8
722*/
Erik Språng242e22b2015-05-11 10:17:43 +0200723RTCPSender::BuildResult RTCPSender::BuildRPSI(RtcpContext* ctx) {
724 if (ctx->feedback_state.send_payload_type == 0xFF)
725 return BuildResult::kError;
726
Erik Språng61be2a42015-04-27 13:32:52 +0200727 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200728 if (ctx->position + 24 >= IP_PACKET_SIZE)
729 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000730
Erik Språng61be2a42015-04-27 13:32:52 +0200731 // add Reference Picture Selection Indication
732 uint8_t FMT = 3;
Erik Språng242e22b2015-05-11 10:17:43 +0200733 *ctx->AllocateData(1) = 0x80 + FMT;
734 *ctx->AllocateData(1) = 206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000735
Erik Språng61be2a42015-04-27 13:32:52 +0200736 // calc length
737 uint32_t bitsRequired = 7;
738 uint8_t bytesRequired = 1;
Erik Språng242e22b2015-05-11 10:17:43 +0200739 while ((ctx->picture_id >> bitsRequired) > 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200740 bitsRequired += 7;
741 bytesRequired++;
742 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000743
Erik Språng61be2a42015-04-27 13:32:52 +0200744 uint8_t size = 3;
745 if (bytesRequired > 6) {
746 size = 5;
747 } else if (bytesRequired > 2) {
748 size = 4;
749 }
Erik Språng242e22b2015-05-11 10:17:43 +0200750 *ctx->AllocateData(1) = 0;
751 *ctx->AllocateData(1) = size;
niklase@google.com470e71d2011-07-07 08:21:25 +0000752
Erik Språng61be2a42015-04-27 13:32:52 +0200753 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200754 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000755
Erik Språng61be2a42015-04-27 13:32:52 +0200756 // Add the remote SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200757 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200758
759 // calc padding length
760 uint8_t paddingBytes = 4 - ((2 + bytesRequired) % 4);
761 if (paddingBytes == 4)
762 paddingBytes = 0;
763 // add padding length in bits
Erik Språng242e22b2015-05-11 10:17:43 +0200764 *ctx->AllocateData(1) = paddingBytes * 8; // padding can be 0, 8, 16 or 24
Erik Språng61be2a42015-04-27 13:32:52 +0200765
766 // add payload type
Erik Språng242e22b2015-05-11 10:17:43 +0200767 *ctx->AllocateData(1) = ctx->feedback_state.send_payload_type;
Erik Språng61be2a42015-04-27 13:32:52 +0200768
769 // add picture ID
770 for (int i = bytesRequired - 1; i > 0; --i) {
Erik Språng242e22b2015-05-11 10:17:43 +0200771 *ctx->AllocateData(1) =
772 0x80 | static_cast<uint8_t>(ctx->picture_id >> (i * 7));
Erik Språng61be2a42015-04-27 13:32:52 +0200773 }
774 // add last byte of picture ID
Erik Språng242e22b2015-05-11 10:17:43 +0200775 *ctx->AllocateData(1) = static_cast<uint8_t>(ctx->picture_id & 0x7f);
niklase@google.com470e71d2011-07-07 08:21:25 +0000776
Erik Språng61be2a42015-04-27 13:32:52 +0200777 // add padding
778 for (int j = 0; j < paddingBytes; j++) {
Erik Språng242e22b2015-05-11 10:17:43 +0200779 *ctx->AllocateData(1) = 0;
Erik Språng61be2a42015-04-27 13:32:52 +0200780 }
Erik Språng242e22b2015-05-11 10:17:43 +0200781
782 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000783}
784
Erik Språng242e22b2015-05-11 10:17:43 +0200785RTCPSender::BuildResult RTCPSender::BuildREMB(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200786 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200787 if (ctx->position + 20 + 4 * remb_ssrcs_.size() >= IP_PACKET_SIZE)
788 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200789
790 // add application layer feedback
791 uint8_t FMT = 15;
Erik Språng242e22b2015-05-11 10:17:43 +0200792 *ctx->AllocateData(1) = 0x80 + FMT;
793 *ctx->AllocateData(1) = 206;
Erik Språng61be2a42015-04-27 13:32:52 +0200794
Erik Språng242e22b2015-05-11 10:17:43 +0200795 *ctx->AllocateData(1) = 0;
796 *ctx->AllocateData(1) = static_cast<uint8_t>(remb_ssrcs_.size() + 4);
Erik Språng61be2a42015-04-27 13:32:52 +0200797
798 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200799 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200800
801 // Remote SSRC must be 0
Erik Språng242e22b2015-05-11 10:17:43 +0200802 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), 0);
Erik Språng61be2a42015-04-27 13:32:52 +0200803
Erik Språng242e22b2015-05-11 10:17:43 +0200804 *ctx->AllocateData(1) = 'R';
805 *ctx->AllocateData(1) = 'E';
806 *ctx->AllocateData(1) = 'M';
807 *ctx->AllocateData(1) = 'B';
Erik Språng61be2a42015-04-27 13:32:52 +0200808
Erik Språng242e22b2015-05-11 10:17:43 +0200809 *ctx->AllocateData(1) = remb_ssrcs_.size();
Erik Språng61be2a42015-04-27 13:32:52 +0200810 // 6 bit Exp
811 // 18 bit mantissa
812 uint8_t brExp = 0;
813 for (uint32_t i = 0; i < 64; i++) {
Erik Språng242e22b2015-05-11 10:17:43 +0200814 if (remb_bitrate_ <= (0x3FFFFu << i)) {
Erik Språng61be2a42015-04-27 13:32:52 +0200815 brExp = i;
816 break;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000817 }
Erik Språng61be2a42015-04-27 13:32:52 +0200818 }
Erik Språng242e22b2015-05-11 10:17:43 +0200819 const uint32_t brMantissa = (remb_bitrate_ >> brExp);
820 *ctx->AllocateData(1) =
821 static_cast<uint8_t>((brExp << 2) + ((brMantissa >> 16) & 0x03));
822 *ctx->AllocateData(1) = static_cast<uint8_t>(brMantissa >> 8);
823 *ctx->AllocateData(1) = static_cast<uint8_t>(brMantissa);
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000824
Erik Språng242e22b2015-05-11 10:17:43 +0200825 for (size_t i = 0; i < remb_ssrcs_.size(); i++)
826 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remb_ssrcs_[i]);
827
828 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
829 "RTCPSender::REMB");
830
831 return BuildResult::kSuccess;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000832}
833
Erik Språng61be2a42015-04-27 13:32:52 +0200834void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
Erik Språng242e22b2015-05-11 10:17:43 +0200835 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
836 tmmbr_send_ = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000837}
838
Erik Språng242e22b2015-05-11 10:17:43 +0200839RTCPSender::BuildResult RTCPSender::BuildTMMBR(RtcpContext* ctx) {
840 if (ctx->feedback_state.module == NULL)
841 return BuildResult::kError;
Erik Språng61be2a42015-04-27 13:32:52 +0200842 // Before sending the TMMBR check the received TMMBN, only an owner is
843 // allowed to raise the bitrate:
844 // * If the sender is an owner of the TMMBN -> send TMMBR
845 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000846
Erik Språng61be2a42015-04-27 13:32:52 +0200847 // get current bounding set from RTCP receiver
848 bool tmmbrOwner = false;
849 // store in candidateSet, allocates one extra slot
Erik Språng242e22b2015-05-11 10:17:43 +0200850 TMMBRSet* candidateSet = tmmbr_help_.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000851
Erik Språng242e22b2015-05-11 10:17:43 +0200852 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
853 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
Erik Språng61be2a42015-04-27 13:32:52 +0200854 // since RTCPreceiver is not doing the reverse we should be fine
855 int32_t lengthOfBoundingSet =
Erik Språng242e22b2015-05-11 10:17:43 +0200856 ctx->feedback_state.module->BoundingSet(tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +0000857
Erik Språng61be2a42015-04-27 13:32:52 +0200858 if (lengthOfBoundingSet > 0) {
859 for (int32_t i = 0; i < lengthOfBoundingSet; i++) {
Erik Språng242e22b2015-05-11 10:17:43 +0200860 if (candidateSet->Tmmbr(i) == tmmbr_send_ &&
861 candidateSet->PacketOH(i) == packet_oh_send_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200862 // do not send the same tuple
Erik Språng242e22b2015-05-11 10:17:43 +0200863 return BuildResult::kAborted;
Erik Språng61be2a42015-04-27 13:32:52 +0200864 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000865 }
Erik Språng61be2a42015-04-27 13:32:52 +0200866 if (!tmmbrOwner) {
867 // use received bounding set as candidate set
868 // add current tuple
Erik Språng242e22b2015-05-11 10:17:43 +0200869 candidateSet->SetEntry(lengthOfBoundingSet, tmmbr_send_, packet_oh_send_,
870 ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200871 int numCandidates = lengthOfBoundingSet + 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000872
Erik Språng61be2a42015-04-27 13:32:52 +0200873 // find bounding set
874 TMMBRSet* boundingSet = NULL;
Erik Språng242e22b2015-05-11 10:17:43 +0200875 int numBoundingSet = tmmbr_help_.FindTMMBRBoundingSet(boundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200876 if (numBoundingSet > 0 || numBoundingSet <= numCandidates)
Erik Språng242e22b2015-05-11 10:17:43 +0200877 tmmbrOwner = tmmbr_help_.IsOwner(ssrc_, numBoundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200878 if (!tmmbrOwner) {
879 // did not enter bounding set, no meaning to send this request
Erik Språng242e22b2015-05-11 10:17:43 +0200880 return BuildResult::kAborted;
Erik Språng61be2a42015-04-27 13:32:52 +0200881 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000882 }
Erik Språng61be2a42015-04-27 13:32:52 +0200883 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000884
Erik Språng242e22b2015-05-11 10:17:43 +0200885 if (tmmbr_send_) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000886 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200887 if (ctx->position + 20 >= IP_PACKET_SIZE)
888 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000889
Erik Språng61be2a42015-04-27 13:32:52 +0200890 // add TMMBR indicator
891 uint8_t FMT = 3;
Erik Språng242e22b2015-05-11 10:17:43 +0200892 *ctx->AllocateData(1) = 0x80 + FMT;
893 *ctx->AllocateData(1) = 205;
Erik Språng61be2a42015-04-27 13:32:52 +0200894
895 // Length of 4
Erik Språng242e22b2015-05-11 10:17:43 +0200896 *ctx->AllocateData(1) = 0;
897 *ctx->AllocateData(1) = 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000898
899 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200900 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000901
Erik Språng61be2a42015-04-27 13:32:52 +0200902 // RFC 5104 4.2.1.2. Semantics
niklase@google.com470e71d2011-07-07 08:21:25 +0000903
904 // SSRC of media source
Erik Språng242e22b2015-05-11 10:17:43 +0200905 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), 0);
niklase@google.com470e71d2011-07-07 08:21:25 +0000906
907 // Additional Feedback Control Information (FCI)
Erik Språng242e22b2015-05-11 10:17:43 +0200908 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remote_ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000909
Erik Språng242e22b2015-05-11 10:17:43 +0200910 uint32_t bitRate = tmmbr_send_ * 1000;
Erik Språng61be2a42015-04-27 13:32:52 +0200911 uint32_t mmbrExp = 0;
912 for (uint32_t i = 0; i < 64; i++) {
913 if (bitRate <= (0x1FFFFu << i)) {
914 mmbrExp = i;
915 break;
916 }
917 }
918 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
919
Erik Språng242e22b2015-05-11 10:17:43 +0200920 *ctx->AllocateData(1) =
Erik Språng61be2a42015-04-27 13:32:52 +0200921 static_cast<uint8_t>((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
Erik Språng242e22b2015-05-11 10:17:43 +0200922 *ctx->AllocateData(1) = static_cast<uint8_t>(mmbrMantissa >> 7);
923 *ctx->AllocateData(1) = static_cast<uint8_t>(
924 (mmbrMantissa << 1) + ((packet_oh_send_ >> 8) & 0x01));
925 *ctx->AllocateData(1) = static_cast<uint8_t>(packet_oh_send_);
Erik Språng61be2a42015-04-27 13:32:52 +0200926 }
Erik Språng242e22b2015-05-11 10:17:43 +0200927 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +0200928}
929
Erik Språng242e22b2015-05-11 10:17:43 +0200930RTCPSender::BuildResult RTCPSender::BuildTMMBN(RtcpContext* ctx) {
931 TMMBRSet* boundingSet = tmmbr_help_.BoundingSetToSend();
Erik Språng61be2a42015-04-27 13:32:52 +0200932 if (boundingSet == NULL)
Erik Språng242e22b2015-05-11 10:17:43 +0200933 return BuildResult::kError;
Erik Språng61be2a42015-04-27 13:32:52 +0200934
935 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200936 if (ctx->position + 12 + boundingSet->lengthOfSet() * 8 >= IP_PACKET_SIZE) {
Erik Språng61be2a42015-04-27 13:32:52 +0200937 LOG(LS_WARNING) << "Failed to build TMMBN.";
Erik Språng242e22b2015-05-11 10:17:43 +0200938 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200939 }
940
941 uint8_t FMT = 4;
942 // add TMMBN indicator
Erik Språng242e22b2015-05-11 10:17:43 +0200943 *ctx->AllocateData(1) = 0x80 + FMT;
944 *ctx->AllocateData(1) = 205;
Erik Språng61be2a42015-04-27 13:32:52 +0200945
946 // Add length later
Erik Språng242e22b2015-05-11 10:17:43 +0200947 int posLength = ctx->position;
948 ctx->AllocateData(2);
Erik Språng61be2a42015-04-27 13:32:52 +0200949
950 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200951 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200952
953 // RFC 5104 4.2.2.2. Semantics
954
955 // SSRC of media source
Erik Språng242e22b2015-05-11 10:17:43 +0200956 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), 0);
Erik Språng61be2a42015-04-27 13:32:52 +0200957
958 // Additional Feedback Control Information (FCI)
959 int numBoundingSet = 0;
960 for (uint32_t n = 0; n < boundingSet->lengthOfSet(); n++) {
961 if (boundingSet->Tmmbr(n) > 0) {
962 uint32_t tmmbrSSRC = boundingSet->Ssrc(n);
Erik Språng242e22b2015-05-11 10:17:43 +0200963 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), tmmbrSSRC);
Erik Språng61be2a42015-04-27 13:32:52 +0200964
965 uint32_t bitRate = boundingSet->Tmmbr(n) * 1000;
966 uint32_t mmbrExp = 0;
967 for (int i = 0; i < 64; i++) {
968 if (bitRate <= (0x1FFFFu << i)) {
969 mmbrExp = i;
andresp@webrtc.org523f9372013-04-11 11:30:39 +0000970 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000971 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +0000972 }
Erik Språng61be2a42015-04-27 13:32:52 +0200973 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
974 uint32_t measuredOH = boundingSet->PacketOH(n);
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000975
Erik Språng242e22b2015-05-11 10:17:43 +0200976 *ctx->AllocateData(1) =
Erik Språng61be2a42015-04-27 13:32:52 +0200977 static_cast<uint8_t>((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
Erik Språng242e22b2015-05-11 10:17:43 +0200978 *ctx->AllocateData(1) = static_cast<uint8_t>(mmbrMantissa >> 7);
979 *ctx->AllocateData(1) = static_cast<uint8_t>((mmbrMantissa << 1) +
980 ((measuredOH >> 8) & 0x01));
981 *ctx->AllocateData(1) = static_cast<uint8_t>(measuredOH);
Erik Språng61be2a42015-04-27 13:32:52 +0200982 numBoundingSet++;
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000983 }
Erik Språng61be2a42015-04-27 13:32:52 +0200984 }
985 uint16_t length = static_cast<uint16_t>(2 + 2 * numBoundingSet);
Erik Språng242e22b2015-05-11 10:17:43 +0200986 ctx->buffer[posLength++] = static_cast<uint8_t>(length >> 8);
987 ctx->buffer[posLength] = static_cast<uint8_t>(length);
988
989 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000990}
991
Erik Språng242e22b2015-05-11 10:17:43 +0200992RTCPSender::BuildResult RTCPSender::BuildAPP(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200993 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200994 if (app_data_ == NULL) {
Erik Språng61be2a42015-04-27 13:32:52 +0200995 LOG(LS_WARNING) << "Failed to build app specific.";
Erik Språng242e22b2015-05-11 10:17:43 +0200996 return BuildResult::kError;
Erik Språng61be2a42015-04-27 13:32:52 +0200997 }
Erik Språng242e22b2015-05-11 10:17:43 +0200998 if (ctx->position + 12 + app_length_ >= IP_PACKET_SIZE) {
Erik Språng61be2a42015-04-27 13:32:52 +0200999 LOG(LS_WARNING) << "Failed to build app specific.";
Erik Språng242e22b2015-05-11 10:17:43 +02001000 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +02001001 }
Erik Språng242e22b2015-05-11 10:17:43 +02001002 *ctx->AllocateData(1) = 0x80 + app_sub_type_;
Erik Språng61be2a42015-04-27 13:32:52 +02001003
1004 // Add APP ID
Erik Språng242e22b2015-05-11 10:17:43 +02001005 *ctx->AllocateData(1) = 204;
Erik Språng61be2a42015-04-27 13:32:52 +02001006
Erik Språng242e22b2015-05-11 10:17:43 +02001007 uint16_t length = (app_length_ >> 2) + 2; // include SSRC and name
1008 *ctx->AllocateData(1) = static_cast<uint8_t>(length >> 8);
1009 *ctx->AllocateData(1) = static_cast<uint8_t>(length);
Erik Språng61be2a42015-04-27 13:32:52 +02001010
1011 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +02001012 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +02001013
1014 // Add our application name
Erik Språng242e22b2015-05-11 10:17:43 +02001015 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), app_name_);
Erik Språng61be2a42015-04-27 13:32:52 +02001016
1017 // Add the data
Erik Språng242e22b2015-05-11 10:17:43 +02001018 memcpy(ctx->AllocateData(app_length_), app_data_.get(), app_length_);
1019
1020 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +02001021}
1022
Erik Språng242e22b2015-05-11 10:17:43 +02001023RTCPSender::BuildResult RTCPSender::BuildNACK(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +02001024 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +02001025 if (ctx->position + 16 >= IP_PACKET_SIZE) {
Erik Språng61be2a42015-04-27 13:32:52 +02001026 LOG(LS_WARNING) << "Failed to build NACK.";
Erik Språng242e22b2015-05-11 10:17:43 +02001027 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +02001028 }
1029
Erik Språng242e22b2015-05-11 10:17:43 +02001030 // int size, uint16_t* nack_list
Erik Språng61be2a42015-04-27 13:32:52 +02001031 // add nack list
1032 uint8_t FMT = 1;
Erik Språng242e22b2015-05-11 10:17:43 +02001033 *ctx->AllocateData(1) = 0x80 + FMT;
1034 *ctx->AllocateData(1) = 205;
Erik Språng61be2a42015-04-27 13:32:52 +02001035
Erik Språng242e22b2015-05-11 10:17:43 +02001036 *ctx->AllocateData(1) = 0;
1037 int nack_size_pos_ = ctx->position;
1038 *ctx->AllocateData(1) = 3; // setting it to one kNACK signal as default
Erik Språng61be2a42015-04-27 13:32:52 +02001039
1040 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +02001041 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +02001042
1043 // Add the remote SSRC
Erik Språng242e22b2015-05-11 10:17:43 +02001044 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +02001045
1046 // Build NACK bitmasks and write them to the RTCP message.
1047 // The nack list should be sorted and not contain duplicates if one
1048 // wants to build the smallest rtcp nack packet.
1049 int numOfNackFields = 0;
1050 int maxNackFields =
Erik Språng242e22b2015-05-11 10:17:43 +02001051 std::min<int>(kRtcpMaxNackFields, (IP_PACKET_SIZE - ctx->position) / 4);
Erik Språng61be2a42015-04-27 13:32:52 +02001052 int i = 0;
Erik Språng242e22b2015-05-11 10:17:43 +02001053 while (i < ctx->nack_size && numOfNackFields < maxNackFields) {
1054 uint16_t nack = ctx->nack_list[i++];
Erik Språng61be2a42015-04-27 13:32:52 +02001055 uint16_t bitmask = 0;
Erik Språng242e22b2015-05-11 10:17:43 +02001056 while (i < ctx->nack_size) {
1057 int shift = static_cast<uint16_t>(ctx->nack_list[i] - nack) - 1;
Erik Språng61be2a42015-04-27 13:32:52 +02001058 if (shift >= 0 && shift <= 15) {
1059 bitmask |= (1 << shift);
1060 ++i;
1061 } else {
1062 break;
1063 }
1064 }
1065 // Write the sequence number and the bitmask to the packet.
Erik Språng242e22b2015-05-11 10:17:43 +02001066 assert(ctx->position + 4 < IP_PACKET_SIZE);
1067 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2), nack);
1068 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2), bitmask);
Erik Språng61be2a42015-04-27 13:32:52 +02001069 numOfNackFields++;
1070 }
Erik Språng242e22b2015-05-11 10:17:43 +02001071 ctx->buffer[nack_size_pos_] = static_cast<uint8_t>(2 + numOfNackFields);
Erik Språng61be2a42015-04-27 13:32:52 +02001072
Erik Språng242e22b2015-05-11 10:17:43 +02001073 if (i != ctx->nack_size)
Erik Språng61be2a42015-04-27 13:32:52 +02001074 LOG(LS_WARNING) << "Nack list too large for one packet.";
1075
1076 // Report stats.
1077 NACKStringBuilder stringBuilder;
1078 for (int idx = 0; idx < i; ++idx) {
Erik Språng242e22b2015-05-11 10:17:43 +02001079 stringBuilder.PushNACK(ctx->nack_list[idx]);
1080 nack_stats_.ReportRequest(ctx->nack_list[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +02001081 }
Erik Språng61be2a42015-04-27 13:32:52 +02001082 packet_type_counter_.nack_requests = nack_stats_.requests();
1083 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +02001084
1085 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
1086 "RTCPSender::NACK", "nacks",
1087 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
1088 ++packet_type_counter_.nack_packets;
1089 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
1090 ssrc_, packet_type_counter_.nack_packets);
1091
1092 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +02001093}
1094
Erik Språng242e22b2015-05-11 10:17:43 +02001095RTCPSender::BuildResult RTCPSender::BuildBYE(RtcpContext* ctx) {
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001096 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +02001097 if (ctx->position + 8 >= IP_PACKET_SIZE)
1098 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +00001099
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001100 // Add a bye packet
1101 // Number of SSRC + CSRCs.
Erik Språng242e22b2015-05-11 10:17:43 +02001102 *ctx->AllocateData(1) = static_cast<uint8_t>(0x80 + 1 + csrcs_.size());
1103 *ctx->AllocateData(1) = 203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001104
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001105 // length
Erik Språng242e22b2015-05-11 10:17:43 +02001106 *ctx->AllocateData(1) = 0;
1107 *ctx->AllocateData(1) = static_cast<uint8_t>(1 + csrcs_.size());
niklase@google.com470e71d2011-07-07 08:21:25 +00001108
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001109 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +02001110 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +00001111
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001112 // add CSRCs
Erik Språng242e22b2015-05-11 10:17:43 +02001113 for (size_t i = 0; i < csrcs_.size(); i++)
1114 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), csrcs_[i]);
niklase@google.com470e71d2011-07-07 08:21:25 +00001115
Erik Språng242e22b2015-05-11 10:17:43 +02001116 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +00001117}
1118
Erik Språng242e22b2015-05-11 10:17:43 +02001119RTCPSender::BuildResult RTCPSender::BuildReceiverReferenceTime(
1120 RtcpContext* ctx) {
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001121 const int kRrTimeBlockLength = 20;
Erik Språng242e22b2015-05-11 10:17:43 +02001122 if (ctx->position + kRrTimeBlockLength >= IP_PACKET_SIZE)
1123 return BuildResult::kTruncated;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001124
Erik Språng61be2a42015-04-27 13:32:52 +02001125 if (last_xr_rr_.size() >= RTCP_NUMBER_OF_SR)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001126 last_xr_rr_.erase(last_xr_rr_.begin());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001127 last_xr_rr_.insert(std::pair<uint32_t, int64_t>(
Erik Språng242e22b2015-05-11 10:17:43 +02001128 RTCPUtility::MidNtp(ctx->ntp_sec, ctx->ntp_frac),
1129 Clock::NtpToMs(ctx->ntp_sec, ctx->ntp_frac)));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001130
1131 // Add XR header.
Erik Språng242e22b2015-05-11 10:17:43 +02001132 *ctx->AllocateData(1) = 0x80;
1133 *ctx->AllocateData(1) = 207;
1134 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1135 4); // XR packet length.
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001136
1137 // Add our own SSRC.
Erik Språng242e22b2015-05-11 10:17:43 +02001138 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001139
1140 // 0 1 2 3
1141 // 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
1142 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1143 // | BT=4 | reserved | block length = 2 |
1144 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1145 // | NTP timestamp, most significant word |
1146 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1147 // | NTP timestamp, least significant word |
1148 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1149
1150 // Add Receiver Reference Time Report block.
Erik Språng242e22b2015-05-11 10:17:43 +02001151 *ctx->AllocateData(1) = 4; // BT.
1152 *ctx->AllocateData(1) = 0; // Reserved.
1153 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1154 2); // Block length.
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001155
1156 // NTP timestamp.
Erik Språng242e22b2015-05-11 10:17:43 +02001157 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ctx->ntp_sec);
1158 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ctx->ntp_frac);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001159
Erik Språng242e22b2015-05-11 10:17:43 +02001160 return BuildResult::kSuccess;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001161}
1162
Erik Språng242e22b2015-05-11 10:17:43 +02001163RTCPSender::BuildResult RTCPSender::BuildDlrr(RtcpContext* ctx) {
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001164 const int kDlrrBlockLength = 24;
Erik Språng242e22b2015-05-11 10:17:43 +02001165 if (ctx->position + kDlrrBlockLength >= IP_PACKET_SIZE)
1166 return BuildResult::kTruncated;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001167
1168 // Add XR header.
Erik Språng242e22b2015-05-11 10:17:43 +02001169 *ctx->AllocateData(1) = 0x80;
1170 *ctx->AllocateData(1) = 207;
1171 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1172 5); // XR packet length.
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001173
1174 // Add our own SSRC.
Erik Språng242e22b2015-05-11 10:17:43 +02001175 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001176
1177 // 0 1 2 3
1178 // 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
1179 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1180 // | BT=5 | reserved | block length |
1181 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1182 // | SSRC_1 (SSRC of first receiver) | sub-
1183 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1184 // | last RR (LRR) | 1
1185 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1186 // | delay since last RR (DLRR) |
1187 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1188 // | SSRC_2 (SSRC of second receiver) | sub-
1189 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1190 // : ... : 2
1191
1192 // Add DLRR sub block.
Erik Språng242e22b2015-05-11 10:17:43 +02001193 *ctx->AllocateData(1) = 5; // BT.
1194 *ctx->AllocateData(1) = 0; // Reserved.
1195 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1196 3); // Block length.
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001197
1198 // NTP timestamp.
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001199
Erik Språng242e22b2015-05-11 10:17:43 +02001200 const RtcpReceiveTimeInfo& info = ctx->feedback_state.last_xr_rr;
1201 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), info.sourceSSRC);
1202 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), info.lastRR);
1203 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4),
1204 info.delaySinceLastRR);
1205
1206 return BuildResult::kSuccess;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001207}
1208
Erik Språng242e22b2015-05-11 10:17:43 +02001209// TODO(sprang): Add a unit test for this, or remove if the code isn't used.
1210RTCPSender::BuildResult RTCPSender::BuildVoIPMetric(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +02001211 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +02001212 if (ctx->position + 44 >= IP_PACKET_SIZE)
1213 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +00001214
Erik Språng61be2a42015-04-27 13:32:52 +02001215 // Add XR header
Erik Språng242e22b2015-05-11 10:17:43 +02001216 *ctx->AllocateData(1) = 0x80;
1217 *ctx->AllocateData(1) = 207;
niklase@google.com470e71d2011-07-07 08:21:25 +00001218
Erik Språng242e22b2015-05-11 10:17:43 +02001219 uint32_t XRLengthPos = ctx->position;
niklase@google.com470e71d2011-07-07 08:21:25 +00001220
Erik Språng61be2a42015-04-27 13:32:52 +02001221 // handle length later on
Erik Språng242e22b2015-05-11 10:17:43 +02001222 ctx->AllocateData(2);
niklase@google.com470e71d2011-07-07 08:21:25 +00001223
Erik Språng61be2a42015-04-27 13:32:52 +02001224 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +02001225 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +00001226
Erik Språng61be2a42015-04-27 13:32:52 +02001227 // Add a VoIP metrics block
Erik Språng242e22b2015-05-11 10:17:43 +02001228 *ctx->AllocateData(1) = 7;
1229 *ctx->AllocateData(1) = 0;
1230 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2), 8);
niklase@google.com470e71d2011-07-07 08:21:25 +00001231
Erik Språng61be2a42015-04-27 13:32:52 +02001232 // Add the remote SSRC
Erik Språng242e22b2015-05-11 10:17:43 +02001233 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remote_ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +00001234
Erik Språng242e22b2015-05-11 10:17:43 +02001235 *ctx->AllocateData(1) = xr_voip_metric_.lossRate;
1236 *ctx->AllocateData(1) = xr_voip_metric_.discardRate;
1237 *ctx->AllocateData(1) = xr_voip_metric_.burstDensity;
1238 *ctx->AllocateData(1) = xr_voip_metric_.gapDensity;
niklase@google.com470e71d2011-07-07 08:21:25 +00001239
Erik Språng242e22b2015-05-11 10:17:43 +02001240 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1241 xr_voip_metric_.burstDuration);
1242 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1243 xr_voip_metric_.gapDuration);
niklase@google.com470e71d2011-07-07 08:21:25 +00001244
Erik Språng242e22b2015-05-11 10:17:43 +02001245 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1246 xr_voip_metric_.roundTripDelay);
1247 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1248 xr_voip_metric_.endSystemDelay);
niklase@google.com470e71d2011-07-07 08:21:25 +00001249
Erik Språng242e22b2015-05-11 10:17:43 +02001250 *ctx->AllocateData(1) = xr_voip_metric_.signalLevel;
1251 *ctx->AllocateData(1) = xr_voip_metric_.noiseLevel;
1252 *ctx->AllocateData(1) = xr_voip_metric_.RERL;
1253 *ctx->AllocateData(1) = xr_voip_metric_.Gmin;
niklase@google.com470e71d2011-07-07 08:21:25 +00001254
Erik Språng242e22b2015-05-11 10:17:43 +02001255 *ctx->AllocateData(1) = xr_voip_metric_.Rfactor;
1256 *ctx->AllocateData(1) = xr_voip_metric_.extRfactor;
1257 *ctx->AllocateData(1) = xr_voip_metric_.MOSLQ;
1258 *ctx->AllocateData(1) = xr_voip_metric_.MOSCQ;
niklase@google.com470e71d2011-07-07 08:21:25 +00001259
Erik Språng242e22b2015-05-11 10:17:43 +02001260 *ctx->AllocateData(1) = xr_voip_metric_.RXconfig;
1261 *ctx->AllocateData(1) = 0; // reserved
niklase@google.com470e71d2011-07-07 08:21:25 +00001262
Erik Språng242e22b2015-05-11 10:17:43 +02001263 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1264 xr_voip_metric_.JBnominal);
1265 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1266 xr_voip_metric_.JBmax);
1267 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1268 xr_voip_metric_.JBabsMax);
niklase@google.com470e71d2011-07-07 08:21:25 +00001269
Erik Språng242e22b2015-05-11 10:17:43 +02001270 ByteWriter<uint16_t>::WriteBigEndian(&ctx->buffer[XRLengthPos], 10);
1271
1272 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +00001273}
1274
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001275int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +02001276 RTCPPacketType packetType,
1277 int32_t nack_size,
1278 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001279 bool repeat,
1280 uint64_t pictureID) {
Erik Språng242e22b2015-05-11 10:17:43 +02001281 return SendCompoundRTCP(
1282 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
1283 nack_size, nack_list, repeat, pictureID);
1284}
1285
1286int32_t RTCPSender::SendCompoundRTCP(
1287 const FeedbackState& feedback_state,
1288 const std::set<RTCPPacketType>& packetTypes,
1289 int32_t nack_size,
1290 const uint16_t* nack_list,
1291 bool repeat,
1292 uint64_t pictureID) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001293 {
Erik Språng242e22b2015-05-11 10:17:43 +02001294 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1295 if (method_ == kRtcpOff) {
Erik Språng61be2a42015-04-27 13:32:52 +02001296 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
1297 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +00001298 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001299 }
1300 uint8_t rtcp_buffer[IP_PACKET_SIZE];
Erik Språng242e22b2015-05-11 10:17:43 +02001301 int rtcp_length =
1302 PrepareRTCP(feedback_state, packetTypes, nack_size, nack_list, repeat,
1303 pictureID, rtcp_buffer, IP_PACKET_SIZE);
Erik Språng61be2a42015-04-27 13:32:52 +02001304
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001305 // Sanity don't send empty packets.
Erik Språng242e22b2015-05-11 10:17:43 +02001306 if (rtcp_length <= 0)
1307 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +02001308
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00001309 return SendToNetwork(rtcp_buffer, static_cast<size_t>(rtcp_length));
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001310}
1311
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001312int RTCPSender::PrepareRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +02001313 const std::set<RTCPPacketType>& packetTypes,
1314 int32_t nack_size,
1315 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001316 bool repeat,
1317 uint64_t pictureID,
1318 uint8_t* rtcp_buffer,
1319 int buffer_size) {
Erik Språng242e22b2015-05-11 10:17:43 +02001320 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001321
Erik Språng242e22b2015-05-11 10:17:43 +02001322 RtcpContext context(feedback_state, nack_size, nack_list, repeat, pictureID,
1323 rtcp_buffer, buffer_size);
1324
1325 // Add all flags as volatile. Non volatile entries will not be overwritten
1326 // and all new volatile flags added will be consumed by the end of this call.
1327 SetFlags(packetTypes, true);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001328
Erik Språng61be2a42015-04-27 13:32:52 +02001329 if (packet_type_counter_.first_packet_time_ms == -1)
Erik Språng242e22b2015-05-11 10:17:43 +02001330 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språng61be2a42015-04-27 13:32:52 +02001331
Erik Språng242e22b2015-05-11 10:17:43 +02001332 bool generate_report;
1333 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
1334 // Report type already explicitly set, don't automatically populate.
1335 generate_report = true;
1336 DCHECK(ConsumeFlag(kRtcpReport) == false);
1337 } else {
1338 generate_report =
1339 (ConsumeFlag(kRtcpReport) && method_ == kRtcpNonCompound) ||
1340 method_ == kRtcpCompound;
1341 if (generate_report)
1342 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +00001343 }
1344
Erik Språng0ea42d32015-06-25 14:46:16 +02001345 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
Erik Språng242e22b2015-05-11 10:17:43 +02001346 SetFlag(kRtcpSdes, true);
1347
1348 // We need to send our NTP even if we haven't received any reports.
1349 clock_->CurrentNtp(context.ntp_sec, context.ntp_frac);
1350
1351 if (generate_report) {
1352 if (!sending_ && xr_send_receiver_reference_time_enabled_)
1353 SetFlag(kRtcpXrReceiverReferenceTime, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001354 if (feedback_state.has_last_xr_rr)
Erik Språng242e22b2015-05-11 10:17:43 +02001355 SetFlag(kRtcpXrDlrrReportBlock, true);
1356
1357 // generate next time to send an RTCP report
Erik Språng61be2a42015-04-27 13:32:52 +02001358 // seeded from RTP constructor
1359 int32_t random = rand() % 1000;
1360 int32_t timeToNext = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001361
Erik Språng242e22b2015-05-11 10:17:43 +02001362 if (audio_) {
Erik Språng61be2a42015-04-27 13:32:52 +02001363 timeToNext = (RTCP_INTERVAL_AUDIO_MS / 2) +
1364 (RTCP_INTERVAL_AUDIO_MS * random / 1000);
1365 } else {
1366 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
Erik Språng242e22b2015-05-11 10:17:43 +02001367 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +02001368 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
1369 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
1370 if (send_bitrate_kbit != 0)
1371 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001372 }
Erik Språng61be2a42015-04-27 13:32:52 +02001373 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
1374 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
1375 timeToNext = (minIntervalMs / 2) + (minIntervalMs * random / 1000);
1376 }
Erik Språng242e22b2015-05-11 10:17:43 +02001377 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001378
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001379 StatisticianMap statisticians =
1380 receive_statistics_->GetActiveStatisticians();
1381 if (!statisticians.empty()) {
Erik Språng61be2a42015-04-27 13:32:52 +02001382 for (auto it = statisticians.begin(); it != statisticians.end(); ++it) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001383 RTCPReportBlock report_block;
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001384 if (PrepareReport(feedback_state, it->first, it->second,
1385 &report_block)) {
1386 AddReportBlock(report_block);
Erik Språng61be2a42015-04-27 13:32:52 +02001387 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001388 }
Erik Språng242e22b2015-05-11 10:17:43 +02001389 if (extended_jitter_report_enabled_)
1390 SetFlag(kRtcpTransmissionTimeOffset, true);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001391 }
1392 }
1393
Erik Språng242e22b2015-05-11 10:17:43 +02001394 auto it = report_flags_.begin();
1395 while (it != report_flags_.end()) {
1396 auto builder = builders_.find(it->type);
1397 DCHECK(builder != builders_.end());
1398 if (it->is_volatile) {
1399 report_flags_.erase(it++);
1400 } else {
1401 ++it;
Erik Språng61be2a42015-04-27 13:32:52 +02001402 }
Erik Språng242e22b2015-05-11 10:17:43 +02001403
1404 uint32_t start_position = context.position;
Erik Språng0ea42d32015-06-25 14:46:16 +02001405 BuildResult result = (this->*(builder->second))(&context);
Erik Språng242e22b2015-05-11 10:17:43 +02001406 switch (result) {
1407 case BuildResult::kError:
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001408 return -1;
Erik Språng242e22b2015-05-11 10:17:43 +02001409 case BuildResult::kTruncated:
1410 return context.position;
1411 case BuildResult::kAborted:
1412 context.position = start_position;
1413 FALLTHROUGH();
1414 case BuildResult::kSuccess:
1415 continue;
Erik Språng61be2a42015-04-27 13:32:52 +02001416 default:
Erik Språng242e22b2015-05-11 10:17:43 +02001417 abort();
Erik Språng61be2a42015-04-27 13:32:52 +02001418 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001419 }
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001420
1421 if (packet_type_counter_observer_ != NULL) {
1422 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
Erik Språng242e22b2015-05-11 10:17:43 +02001423 remote_ssrc_, packet_type_counter_);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001424 }
1425
Erik Språng242e22b2015-05-11 10:17:43 +02001426 DCHECK(AllVolatileFlagsConsumed());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001427
Erik Språng242e22b2015-05-11 10:17:43 +02001428 return context.position;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001429}
1430
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001431bool RTCPSender::PrepareReport(const FeedbackState& feedback_state,
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001432 uint32_t ssrc,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001433 StreamStatistician* statistician,
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001434 RTCPReportBlock* report_block) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001435 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +00001436 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001437 if (!statistician->GetStatistics(&stats, true))
1438 return false;
1439 report_block->fractionLost = stats.fraction_lost;
1440 report_block->cumulativeLost = stats.cumulative_lost;
1441 report_block->extendedHighSeqNum =
1442 stats.extended_max_sequence_number;
1443 report_block->jitter = stats.jitter;
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001444 report_block->remoteSSRC = ssrc;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001445
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001446 // TODO(sprang): Do we really need separate time stamps for each report?
1447 // Get our NTP as late as possible to avoid a race.
1448 uint32_t ntp_secs;
1449 uint32_t ntp_frac;
1450 clock_->CurrentNtp(ntp_secs, ntp_frac);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001451
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001452 // Delay since last received report.
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001453 uint32_t delaySinceLastReceivedSR = 0;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001454 if ((feedback_state.last_rr_ntp_secs != 0) ||
1455 (feedback_state.last_rr_ntp_frac != 0)) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001456 // Get the 16 lowest bits of seconds and the 16 highest bits of fractions.
1457 uint32_t now = ntp_secs & 0x0000FFFF;
Erik Språng61be2a42015-04-27 13:32:52 +02001458 now <<= 16;
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001459 now += (ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001460
Erik Språng61be2a42015-04-27 13:32:52 +02001461 uint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
1462 receiveTime <<= 16;
1463 receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001464
1465 delaySinceLastReceivedSR = now-receiveTime;
1466 }
1467 report_block->delaySinceLastSR = delaySinceLastReceivedSR;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001468 report_block->lastSR = feedback_state.remote_sr;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001469 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +00001470}
1471
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001472int32_t RTCPSender::SendToNetwork(const uint8_t* dataBuffer, size_t length) {
Erik Språng242e22b2015-05-11 10:17:43 +02001473 CriticalSectionScoped lock(critical_section_transport_.get());
1474 if (cbTransport_) {
1475 if (cbTransport_->SendRTCPPacket(id_, dataBuffer, length) > 0)
Erik Språng61be2a42015-04-27 13:32:52 +02001476 return 0;
1477 }
1478 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001479}
1480
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001481void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
1482 assert(csrcs.size() <= kRtpCsrcSize);
Erik Språng242e22b2015-05-11 10:17:43 +02001483 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001484 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +00001485}
1486
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001487int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
1488 uint32_t name,
1489 const uint8_t* data,
1490 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +02001491 if (length % 4 != 0) {
1492 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
1493 return -1;
1494 }
Erik Språng242e22b2015-05-11 10:17:43 +02001495 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +00001496
Erik Språng242e22b2015-05-11 10:17:43 +02001497 SetFlag(kRtcpApp, true);
1498 app_sub_type_ = subType;
1499 app_name_ = name;
1500 app_data_.reset(new uint8_t[length]);
1501 app_length_ = length;
1502 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +02001503 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001504}
1505
Erik Språng61be2a42015-04-27 13:32:52 +02001506int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
Erik Språng242e22b2015-05-11 10:17:43 +02001507 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1508 memcpy(&xr_voip_metric_, VoIPMetric, sizeof(RTCPVoIPMetric));
niklase@google.com470e71d2011-07-07 08:21:25 +00001509
Erik Språng242e22b2015-05-11 10:17:43 +02001510 SetFlag(kRtcpXrVoipMetric, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001511 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001512}
1513
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001514void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +02001515 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1516 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001517}
1518
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00001519bool RTCPSender::RtcpXrReceiverReferenceTime() const {
Erik Språng242e22b2015-05-11 10:17:43 +02001520 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1521 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00001522}
1523
niklase@google.com470e71d2011-07-07 08:21:25 +00001524// no callbacks allowed inside this function
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001525int32_t RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
1526 uint32_t maxBitrateKbit) {
Erik Språng242e22b2015-05-11 10:17:43 +02001527 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +00001528
Erik Språng242e22b2015-05-11 10:17:43 +02001529 if (0 == tmmbr_help_.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit)) {
1530 SetFlag(kRtcpTmmbn, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001531 return 0;
1532 }
1533 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001534}
Erik Språng61be2a42015-04-27 13:32:52 +02001535
Erik Språng242e22b2015-05-11 10:17:43 +02001536void RTCPSender::SetFlag(RTCPPacketType type, bool is_volatile) {
1537 report_flags_.insert(ReportFlag(type, is_volatile));
1538}
1539
1540void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
1541 bool is_volatile) {
1542 for (RTCPPacketType type : types)
1543 SetFlag(type, is_volatile);
1544}
1545
1546bool RTCPSender::IsFlagPresent(RTCPPacketType type) const {
1547 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
1548}
1549
1550bool RTCPSender::ConsumeFlag(RTCPPacketType type, bool forced) {
1551 auto it = report_flags_.find(ReportFlag(type, false));
1552 if (it == report_flags_.end())
1553 return false;
1554 if (it->is_volatile || forced)
1555 report_flags_.erase((it));
1556 return true;
1557}
1558
1559bool RTCPSender::AllVolatileFlagsConsumed() const {
1560 for (const ReportFlag& flag : report_flags_) {
1561 if (flag.is_volatile)
1562 return false;
1563 }
1564 return true;
1565}
1566
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001567} // namespace webrtc