blob: 5f2eb759c96937cccb48d44f421e4f8a22a4c534 [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
stefan@webrtc.org9354cc92012-06-07 08:10:14 +000013#include <string.h> // memcpy
niklase@google.com470e71d2011-07-07 08:21:25 +000014
Danil Chapovalov70ffead2016-07-20 15:26:59 +020015#include <utility>
16
Erik Språng61be2a42015-04-27 13:32:52 +020017#include "webrtc/base/checks.h"
kwiberg4485ffb2016-04-26 08:14:39 -070018#include "webrtc/base/constructormagic.h"
Peter Boströmebc0b4e2015-10-28 16:39:33 +010019#include "webrtc/base/logging.h"
tommie4f96502015-10-20 23:00:48 -070020#include "webrtc/base/trace_event.h"
ossuf515ab82016-12-07 04:52:58 -080021#include "webrtc/call/call.h"
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000022#include "webrtc/common_types.h"
skvladcc91d282016-10-03 18:31:22 -070023#include "webrtc/logging/rtc_event_log/rtc_event_log.h"
danilchap0219c9b2015-11-18 05:56:53 -080024#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/app.h"
danilchap50c51362015-11-22 09:03:11 -080025#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/bye.h"
danilchap2f7dea12016-01-13 02:03:04 -080026#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/compound_packet.h"
Danil Chapovalov256e5b22016-01-15 14:16:24 +010027#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_reports.h"
Danil Chapovalov5679da12016-01-15 13:19:53 +010028#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/fir.h"
danilchapa8890a52015-12-22 03:43:04 -080029#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/nack.h"
danilchapf8385ad2015-11-27 05:36:09 -080030#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/pli.h"
Danil Chapovalov97f7e132015-12-04 16:13:30 +010031#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
Danil Chapovalova5eba6c2016-01-15 12:40:15 +010032#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/remb.h"
Danil Chapovalov1567d0b2016-01-15 17:34:27 +010033#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sdes.h"
danilchap34ed2b92016-01-18 02:43:32 -080034#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sender_report.h"
danilchapef3d8052016-01-11 03:31:08 -080035#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbn.h"
danilchap7e8145f2016-01-11 11:49:19 -080036#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbr.h"
sprang233bd872015-09-08 13:25:16 -070037#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
tommie4f96502015-10-20 23:00:48 -070038#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
danilchap42287842017-02-20 06:40:18 -080039#include "webrtc/modules/rtp_rtcp/source/time_util.h"
danilchap13deaad2016-05-24 13:25:27 -070040#include "webrtc/modules/rtp_rtcp/source/tmmbr_help.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000041
niklase@google.com470e71d2011-07-07 08:21:25 +000042namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000043
sprang5e38c962016-12-01 05:18:09 -080044namespace {
45const uint32_t kRtcpAnyExtendedReports =
46 kRtcpXrVoipMetric | kRtcpXrReceiverReferenceTime | kRtcpXrDlrrReportBlock |
47 kRtcpXrTargetBitrate;
48} // namespace
49
Erik Språng61be2a42015-04-27 13:32:52 +020050NACKStringBuilder::NACKStringBuilder()
danilchap162abd32015-12-10 02:39:40 -080051 : stream_(""), count_(0), prevNack_(0), consecutive_(false) {}
edjee@google.com79b02892013-04-04 19:43:34 +000052
pbos@webrtc.orgf3e4cee2013-07-31 15:17:19 +000053NACKStringBuilder::~NACKStringBuilder() {}
54
danilchap162abd32015-12-10 02:39:40 -080055void NACKStringBuilder::PushNACK(uint16_t nack) {
Erik Språng242e22b2015-05-11 10:17:43 +020056 if (count_ == 0) {
57 stream_ << nack;
58 } else if (nack == prevNack_ + 1) {
59 consecutive_ = true;
Erik Språng61be2a42015-04-27 13:32:52 +020060 } else {
Erik Språng242e22b2015-05-11 10:17:43 +020061 if (consecutive_) {
62 stream_ << "-" << prevNack_;
63 consecutive_ = false;
edjee@google.com79b02892013-04-04 19:43:34 +000064 }
Erik Språng242e22b2015-05-11 10:17:43 +020065 stream_ << "," << nack;
Erik Språng61be2a42015-04-27 13:32:52 +020066 }
Erik Språng242e22b2015-05-11 10:17:43 +020067 count_++;
68 prevNack_ = nack;
edjee@google.com79b02892013-04-04 19:43:34 +000069}
70
Erik Språng61be2a42015-04-27 13:32:52 +020071std::string NACKStringBuilder::GetResult() {
Erik Språng242e22b2015-05-11 10:17:43 +020072 if (consecutive_) {
73 stream_ << "-" << prevNack_;
74 consecutive_ = false;
Erik Språng61be2a42015-04-27 13:32:52 +020075 }
Erik Språng242e22b2015-05-11 10:17:43 +020076 return stream_.str();
edjee@google.com79b02892013-04-04 19:43:34 +000077}
78
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000079RTCPSender::FeedbackState::FeedbackState()
80 : send_payload_type(0),
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +000081 packets_sent(0),
82 media_bytes_sent(0),
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000083 send_bitrate(0),
84 last_rr_ntp_secs(0),
85 last_rr_ntp_frac(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000086 remote_sr(0),
Erik Språng61be2a42015-04-27 13:32:52 +020087 has_last_xr_rr(false),
danilchap162abd32015-12-10 02:39:40 -080088 module(nullptr) {}
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000089
danilchap2f7dea12016-01-13 02:03:04 -080090class PacketContainer : public rtcp::CompoundPacket,
Erik Språngf7c57762015-12-04 10:40:35 +010091 public rtcp::RtcpPacket::PacketReadyCallback {
92 public:
terelius429c3452016-01-21 05:42:04 -080093 PacketContainer(Transport* transport, RtcEventLog* event_log)
94 : transport_(transport), event_log_(event_log), bytes_sent_(0) {}
Erik Språngf7c57762015-12-04 10:40:35 +010095 virtual ~PacketContainer() {
96 for (RtcpPacket* packet : appended_packets_)
97 delete packet;
98 }
99
100 void OnPacketReady(uint8_t* data, size_t length) override {
terelius429c3452016-01-21 05:42:04 -0800101 if (transport_->SendRtcp(data, length)) {
Erik Språngf7c57762015-12-04 10:40:35 +0100102 bytes_sent_ += length;
terelius429c3452016-01-21 05:42:04 -0800103 if (event_log_) {
104 event_log_->LogRtcpPacket(kOutgoingPacket, MediaType::ANY, data,
105 length);
106 }
107 }
Erik Språngf7c57762015-12-04 10:40:35 +0100108 }
109
danilchap41befce2016-03-30 11:11:51 -0700110 size_t SendPackets(size_t max_payload_length) {
kwiberg352444f2016-11-28 15:58:53 -0800111 RTC_DCHECK_LE(max_payload_length, IP_PACKET_SIZE);
danilchap41befce2016-03-30 11:11:51 -0700112 uint8_t buffer[IP_PACKET_SIZE];
113 BuildExternalBuffer(buffer, max_payload_length, this);
Erik Språngf7c57762015-12-04 10:40:35 +0100114 return bytes_sent_;
115 }
116
117 private:
118 Transport* transport_;
terelius429c3452016-01-21 05:42:04 -0800119 RtcEventLog* const event_log_;
Erik Språngf7c57762015-12-04 10:40:35 +0100120 size_t bytes_sent_;
terelius429c3452016-01-21 05:42:04 -0800121
122 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(PacketContainer);
Erik Språngf7c57762015-12-04 10:40:35 +0100123};
124
125class RTCPSender::RtcpContext {
126 public:
Erik Språng242e22b2015-05-11 10:17:43 +0200127 RtcpContext(const FeedbackState& feedback_state,
128 int32_t nack_size,
129 const uint16_t* nack_list,
danilchap51813b32016-12-16 02:44:36 -0800130 NtpTime now)
Erik Språngf7c57762015-12-04 10:40:35 +0100131 : feedback_state_(feedback_state),
132 nack_size_(nack_size),
133 nack_list_(nack_list),
danilchap51813b32016-12-16 02:44:36 -0800134 now_(now) {}
Erik Språng242e22b2015-05-11 10:17:43 +0200135
Erik Språngf7c57762015-12-04 10:40:35 +0100136 const FeedbackState& feedback_state_;
137 const int32_t nack_size_;
138 const uint16_t* nack_list_;
danilchap51813b32016-12-16 02:44:36 -0800139 const NtpTime now_;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200140};
141
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000142RTCPSender::RTCPSender(
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000143 bool audio,
144 Clock* clock,
145 ReceiveStatistics* receive_statistics,
sprang86fd9ed2015-09-29 04:45:43 -0700146 RtcpPacketTypeCounterObserver* packet_type_counter_observer,
terelius429c3452016-01-21 05:42:04 -0800147 RtcEventLog* event_log,
sprang86fd9ed2015-09-29 04:45:43 -0700148 Transport* outgoing_transport)
Peter Boströmac547a62015-09-17 23:03:57 +0200149 : audio_(audio),
Erik Språng242e22b2015-05-11 10:17:43 +0200150 clock_(clock),
danilchap47a740b2015-12-15 00:30:07 -0800151 random_(clock_->TimeInMicroseconds()),
pbosda903ea2015-10-02 02:36:56 -0700152 method_(RtcpMode::kOff),
terelius429c3452016-01-21 05:42:04 -0800153 event_log_(event_log),
sprang86fd9ed2015-09-29 04:45:43 -0700154 transport_(outgoing_transport),
Erik Språng242e22b2015-05-11 10:17:43 +0200155 using_nack_(false),
156 sending_(false),
157 remb_enabled_(false),
Erik Språng242e22b2015-05-11 10:17:43 +0200158 next_time_to_send_rtcp_(0),
danilchap71fead22016-08-18 02:01:49 -0700159 timestamp_offset_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000160 last_rtp_timestamp_(0),
161 last_frame_capture_time_ms_(-1),
Erik Språng242e22b2015-05-11 10:17:43 +0200162 ssrc_(0),
163 remote_ssrc_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000164 receive_statistics_(receive_statistics),
niklase@google.com470e71d2011-07-07 08:21:25 +0000165
Erik Språng242e22b2015-05-11 10:17:43 +0200166 sequence_number_fir_(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000167
Erik Språng242e22b2015-05-11 10:17:43 +0200168 remb_bitrate_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000169
danilchap2b616392016-08-18 06:17:42 -0700170 tmmbr_send_bps_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200171 packet_oh_send_(0),
nisse284542b2017-01-10 08:58:32 -0800172 max_packet_size_(IP_PACKET_SIZE - 28), // IPv4 + UDP by default.
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000173
Erik Språng242e22b2015-05-11 10:17:43 +0200174 app_sub_type_(0),
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200175 app_name_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200176 app_data_(nullptr),
177 app_length_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000178
Erik Språng242e22b2015-05-11 10:17:43 +0200179 xr_send_receiver_reference_time_enabled_(false),
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000180 packet_type_counter_observer_(packet_type_counter_observer) {
sprang86fd9ed2015-09-29 04:45:43 -0700181 RTC_DCHECK(transport_ != nullptr);
Erik Språng242e22b2015-05-11 10:17:43 +0200182
183 builders_[kRtcpSr] = &RTCPSender::BuildSR;
184 builders_[kRtcpRr] = &RTCPSender::BuildRR;
Erik Språng0ea42d32015-06-25 14:46:16 +0200185 builders_[kRtcpSdes] = &RTCPSender::BuildSDES;
Erik Språng242e22b2015-05-11 10:17:43 +0200186 builders_[kRtcpPli] = &RTCPSender::BuildPLI;
187 builders_[kRtcpFir] = &RTCPSender::BuildFIR;
Erik Språng242e22b2015-05-11 10:17:43 +0200188 builders_[kRtcpRemb] = &RTCPSender::BuildREMB;
189 builders_[kRtcpBye] = &RTCPSender::BuildBYE;
190 builders_[kRtcpApp] = &RTCPSender::BuildAPP;
191 builders_[kRtcpTmmbr] = &RTCPSender::BuildTMMBR;
192 builders_[kRtcpTmmbn] = &RTCPSender::BuildTMMBN;
193 builders_[kRtcpNack] = &RTCPSender::BuildNACK;
sprang5e38c962016-12-01 05:18:09 -0800194 builders_[kRtcpAnyExtendedReports] = &RTCPSender::BuildExtendedReports;
niklase@google.com470e71d2011-07-07 08:21:25 +0000195}
196
danilchap162abd32015-12-10 02:39:40 -0800197RTCPSender::~RTCPSender() {}
niklase@google.com470e71d2011-07-07 08:21:25 +0000198
pbosda903ea2015-10-02 02:36:56 -0700199RtcpMode RTCPSender::Status() const {
danilchap56036ff2016-03-22 11:14:09 -0700200 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200201 return method_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000202}
203
skvlad1c392cc2016-04-01 14:46:44 -0700204void RTCPSender::SetRTCPStatus(RtcpMode new_method) {
danilchap56036ff2016-03-22 11:14:09 -0700205 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000206
skvlad1c392cc2016-04-01 14:46:44 -0700207 if (method_ == RtcpMode::kOff && new_method != RtcpMode::kOff) {
208 // When switching on, reschedule the next packet
209 next_time_to_send_rtcp_ =
Erik Språng242e22b2015-05-11 10:17:43 +0200210 clock_->TimeInMilliseconds() +
211 (audio_ ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
skvlad1c392cc2016-04-01 14:46:44 -0700212 }
213 method_ = new_method;
niklase@google.com470e71d2011-07-07 08:21:25 +0000214}
215
Erik Språng61be2a42015-04-27 13:32:52 +0200216bool RTCPSender::Sending() const {
danilchap56036ff2016-03-22 11:14:09 -0700217 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200218 return sending_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000219}
220
Erik Språng61be2a42015-04-27 13:32:52 +0200221int32_t RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
222 bool sending) {
223 bool sendRTCPBye = false;
224 {
danilchap56036ff2016-03-22 11:14:09 -0700225 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000226
pbosda903ea2015-10-02 02:36:56 -0700227 if (method_ != RtcpMode::kOff) {
Erik Språng242e22b2015-05-11 10:17:43 +0200228 if (sending == false && sending_ == true) {
Erik Språng61be2a42015-04-27 13:32:52 +0200229 // Trigger RTCP bye
230 sendRTCPBye = true;
231 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000232 }
Erik Språng242e22b2015-05-11 10:17:43 +0200233 sending_ = sending;
Erik Språng61be2a42015-04-27 13:32:52 +0200234 }
235 if (sendRTCPBye)
236 return SendRTCP(feedback_state, kRtcpBye);
237 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000238}
239
Erik Språng61be2a42015-04-27 13:32:52 +0200240bool RTCPSender::REMB() const {
danilchap56036ff2016-03-22 11:14:09 -0700241 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200242 return remb_enabled_;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000243}
244
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000245void RTCPSender::SetREMBStatus(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700246 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200247 remb_enabled_ = enable;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000248}
249
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000250void RTCPSender::SetREMBData(uint32_t bitrate,
251 const std::vector<uint32_t>& ssrcs) {
danilchap56036ff2016-03-22 11:14:09 -0700252 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200253 remb_bitrate_ = bitrate;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000254 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000255
Erik Språng242e22b2015-05-11 10:17:43 +0200256 if (remb_enabled_)
257 SetFlag(kRtcpRemb, false);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000258 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
259 // throttled by the caller.
Erik Språng242e22b2015-05-11 10:17:43 +0200260 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000261}
262
Erik Språng61be2a42015-04-27 13:32:52 +0200263bool RTCPSender::TMMBR() const {
danilchap56036ff2016-03-22 11:14:09 -0700264 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200265 return IsFlagPresent(RTCPPacketType::kRtcpTmmbr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000266}
267
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000268void RTCPSender::SetTMMBRStatus(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700269 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200270 if (enable) {
271 SetFlag(RTCPPacketType::kRtcpTmmbr, false);
272 } else {
273 ConsumeFlag(RTCPPacketType::kRtcpTmmbr, true);
274 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000275}
276
nisse284542b2017-01-10 08:58:32 -0800277void RTCPSender::SetMaxRtpPacketSize(size_t max_packet_size) {
nisse6f142eb2017-02-21 07:32:47 -0800278 rtc::CritScope lock(&critical_section_rtcp_sender_);
nisse284542b2017-01-10 08:58:32 -0800279 max_packet_size_ = max_packet_size;
danilchap41befce2016-03-30 11:11:51 -0700280}
281
danilchap71fead22016-08-18 02:01:49 -0700282void RTCPSender::SetTimestampOffset(uint32_t timestamp_offset) {
danilchap56036ff2016-03-22 11:14:09 -0700283 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap71fead22016-08-18 02:01:49 -0700284 timestamp_offset_ = timestamp_offset;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000285}
286
287void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
288 int64_t capture_time_ms) {
danilchap56036ff2016-03-22 11:14:09 -0700289 rtc::CritScope lock(&critical_section_rtcp_sender_);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000290 last_rtp_timestamp_ = rtp_timestamp;
291 if (capture_time_ms < 0) {
292 // We don't currently get a capture time from VoiceEngine.
Erik Språng242e22b2015-05-11 10:17:43 +0200293 last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000294 } else {
295 last_frame_capture_time_ms_ = capture_time_ms;
296 }
297}
298
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000299void RTCPSender::SetSSRC(uint32_t ssrc) {
danilchap56036ff2016-03-22 11:14:09 -0700300 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000301
Erik Språng242e22b2015-05-11 10:17:43 +0200302 if (ssrc_ != 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200303 // not first SetSSRC, probably due to a collision
304 // schedule a new RTCP report
305 // make sure that we send a RTP packet
Erik Språng242e22b2015-05-11 10:17:43 +0200306 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
Erik Språng61be2a42015-04-27 13:32:52 +0200307 }
Erik Språng242e22b2015-05-11 10:17:43 +0200308 ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000309}
310
Erik Språng61be2a42015-04-27 13:32:52 +0200311void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
danilchap56036ff2016-03-22 11:14:09 -0700312 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200313 remote_ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000314}
315
Peter Boström9ba52f82015-06-01 14:12:28 +0200316int32_t RTCPSender::SetCNAME(const char* c_name) {
317 if (!c_name)
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000318 return -1;
319
kwiberg352444f2016-11-28 15:58:53 -0800320 RTC_DCHECK_LT(strlen(c_name), RTCP_CNAME_SIZE);
danilchap56036ff2016-03-22 11:14:09 -0700321 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200322 cname_ = c_name;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000323 return 0;
324}
325
Erik Språng0ea42d32015-06-25 14:46:16 +0200326int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC, const char* c_name) {
danilchap56036ff2016-03-22 11:14:09 -0700327 RTC_DCHECK(c_name);
kwiberg352444f2016-11-28 15:58:53 -0800328 RTC_DCHECK_LT(strlen(c_name), RTCP_CNAME_SIZE);
danilchap56036ff2016-03-22 11:14:09 -0700329 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200330 if (csrc_cnames_.size() >= kRtpCsrcSize)
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000331 return -1;
Erik Språng0ea42d32015-06-25 14:46:16 +0200332
333 csrc_cnames_[SSRC] = c_name;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000334 return 0;
335}
336
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000337int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
danilchap56036ff2016-03-22 11:14:09 -0700338 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200339 auto it = csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000340
Erik Språng242e22b2015-05-11 10:17:43 +0200341 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000342 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200343
Erik Språng242e22b2015-05-11 10:17:43 +0200344 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000345 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000346}
347
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000348bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
danilchap162abd32015-12-10 02:39:40 -0800349 /*
350 For audio we use a fix 5 sec interval
niklase@google.com470e71d2011-07-07 08:21:25 +0000351
danilchap162abd32015-12-10 02:39:40 -0800352 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
353 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
354 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000355
356
danilchap162abd32015-12-10 02:39:40 -0800357 From RFC 3550
niklase@google.com470e71d2011-07-07 08:21:25 +0000358
danilchap162abd32015-12-10 02:39:40 -0800359 MAX RTCP BW is 5% if the session BW
360 A send report is approximately 65 bytes inc CNAME
361 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000362
danilchap162abd32015-12-10 02:39:40 -0800363 The RECOMMENDED value for the reduced minimum in seconds is 360
364 divided by the session bandwidth in kilobits/second. This minimum
365 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
niklase@google.com470e71d2011-07-07 08:21:25 +0000366
danilchap162abd32015-12-10 02:39:40 -0800367 If the participant has not yet sent an RTCP packet (the variable
368 initial is true), the constant Tmin is set to 2.5 seconds, else it
369 is set to 5 seconds.
niklase@google.com470e71d2011-07-07 08:21:25 +0000370
danilchap162abd32015-12-10 02:39:40 -0800371 The interval between RTCP packets is varied randomly over the
372 range [0.5,1.5] times the calculated interval to avoid unintended
373 synchronization of all participants
niklase@google.com470e71d2011-07-07 08:21:25 +0000374
danilchap162abd32015-12-10 02:39:40 -0800375 if we send
376 If the participant is a sender (we_sent true), the constant C is
377 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
378 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
379 number of senders.
niklase@google.com470e71d2011-07-07 08:21:25 +0000380
danilchap162abd32015-12-10 02:39:40 -0800381 if we receive only
382 If we_sent is not true, the constant C is set
383 to the average RTCP packet size divided by 75% of the RTCP
384 bandwidth. The constant n is set to the number of receivers
385 (members - senders). If the number of senders is greater than
386 25%, senders and receivers are treated together.
niklase@google.com470e71d2011-07-07 08:21:25 +0000387
danilchap162abd32015-12-10 02:39:40 -0800388 reconsideration NOT required for peer-to-peer
389 "timer reconsideration" is
390 employed. This algorithm implements a simple back-off mechanism
391 which causes users to hold back RTCP packet transmission if the
392 group sizes are increasing.
niklase@google.com470e71d2011-07-07 08:21:25 +0000393
danilchap162abd32015-12-10 02:39:40 -0800394 n = number of members
395 C = avg_size/(rtcpBW/4)
niklase@google.com470e71d2011-07-07 08:21:25 +0000396
danilchap162abd32015-12-10 02:39:40 -0800397 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
niklase@google.com470e71d2011-07-07 08:21:25 +0000398
danilchap162abd32015-12-10 02:39:40 -0800399 4. The calculated interval T is set to a number uniformly distributed
400 between 0.5 and 1.5 times the deterministic calculated interval.
niklase@google.com470e71d2011-07-07 08:21:25 +0000401
danilchap162abd32015-12-10 02:39:40 -0800402 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
403 for the fact that the timer reconsideration algorithm converges to
404 a value of the RTCP bandwidth below the intended average
405 */
niklase@google.com470e71d2011-07-07 08:21:25 +0000406
Erik Språng242e22b2015-05-11 10:17:43 +0200407 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000408
danilchap56036ff2016-03-22 11:14:09 -0700409 rtc::CritScope lock(&critical_section_rtcp_sender_);
xians@webrtc.org8738d272011-11-25 13:43:53 +0000410
pbosda903ea2015-10-02 02:36:56 -0700411 if (method_ == RtcpMode::kOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000412 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000413
Erik Språng242e22b2015-05-11 10:17:43 +0200414 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200415 // for video key-frames we want to send the RTCP before the large key-frame
416 // if we have a 100 ms margin
417 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
418 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000419
Erik Språng242e22b2015-05-11 10:17:43 +0200420 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200421 return true;
422 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200423 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200424 // wrap
425 return true;
426 }
427 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000428}
429
danilchap56036ff2016-03-22 11:14:09 -0700430std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSR(const RtcpContext& ctx) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200431 // Timestamp shouldn't be estimated before first media frame.
432 RTC_DCHECK_GE(last_frame_capture_time_ms_, 0);
Erik Språng61be2a42015-04-27 13:32:52 +0200433 // The timestamp of this RTCP packet should be estimated as the timestamp of
434 // the frame being captured at this moment. We are calculating that
435 // timestamp as the last frame's timestamp + the time since the last frame
436 // was captured.
solenbergb19d2882016-10-03 06:22:25 -0700437 uint32_t rtp_rate =
438 (audio_ ? kBogusRtpRateForAudioRtcp : kVideoPayloadTypeFrequency) / 1000;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200439 uint32_t rtp_timestamp =
danilchap71fead22016-08-18 02:01:49 -0700440 timestamp_offset_ + last_rtp_timestamp_ +
solenbergb19d2882016-10-03 06:22:25 -0700441 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) * rtp_rate;
niklase@google.com470e71d2011-07-07 08:21:25 +0000442
Erik Språngf7c57762015-12-04 10:40:35 +0100443 rtcp::SenderReport* report = new rtcp::SenderReport();
danilchap822a16f2016-09-27 09:27:47 -0700444 report->SetSenderSsrc(ssrc_);
danilchap51813b32016-12-16 02:44:36 -0800445 report->SetNtp(ctx.now_);
danilchap822a16f2016-09-27 09:27:47 -0700446 report->SetRtpTimestamp(rtp_timestamp);
447 report->SetPacketCount(ctx.feedback_state_.packets_sent);
448 report->SetOctetCount(ctx.feedback_state_.media_bytes_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000449
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200450 for (auto it : report_blocks_)
danilchap822a16f2016-09-27 09:27:47 -0700451 report->AddReportBlock(it.second);
niklase@google.com470e71d2011-07-07 08:21:25 +0000452
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200453 report_blocks_.clear();
Erik Språngf7c57762015-12-04 10:40:35 +0100454
danilchap56036ff2016-03-22 11:14:09 -0700455 return std::unique_ptr<rtcp::RtcpPacket>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000456}
457
danilchap56036ff2016-03-22 11:14:09 -0700458std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSDES(
Erik Språngf7c57762015-12-04 10:40:35 +0100459 const RtcpContext& ctx) {
Erik Språng0ea42d32015-06-25 14:46:16 +0200460 size_t length_cname = cname_.length();
kwiberg352444f2016-11-28 15:58:53 -0800461 RTC_CHECK_LT(length_cname, RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000462
Erik Språngf7c57762015-12-04 10:40:35 +0100463 rtcp::Sdes* sdes = new rtcp::Sdes();
danilchap822a16f2016-09-27 09:27:47 -0700464 sdes->AddCName(ssrc_, cname_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200465
466 for (const auto it : csrc_cnames_)
danilchap822a16f2016-09-27 09:27:47 -0700467 sdes->AddCName(it.first, it.second);
Erik Språng0ea42d32015-06-25 14:46:16 +0200468
danilchap56036ff2016-03-22 11:14:09 -0700469 return std::unique_ptr<rtcp::RtcpPacket>(sdes);
niklase@google.com470e71d2011-07-07 08:21:25 +0000470}
471
danilchap56036ff2016-03-22 11:14:09 -0700472std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildRR(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100473 rtcp::ReceiverReport* report = new rtcp::ReceiverReport();
danilchap822a16f2016-09-27 09:27:47 -0700474 report->SetSenderSsrc(ssrc_);
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200475 for (auto it : report_blocks_)
danilchap822a16f2016-09-27 09:27:47 -0700476 report->AddReportBlock(it.second);
Erik Språng61be2a42015-04-27 13:32:52 +0200477
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200478 report_blocks_.clear();
danilchap56036ff2016-03-22 11:14:09 -0700479 return std::unique_ptr<rtcp::RtcpPacket>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000480}
481
danilchap56036ff2016-03-22 11:14:09 -0700482std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildPLI(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100483 rtcp::Pli* pli = new rtcp::Pli();
danilchap822a16f2016-09-27 09:27:47 -0700484 pli->SetSenderSsrc(ssrc_);
485 pli->SetMediaSsrc(remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200486
Erik Språng242e22b2015-05-11 10:17:43 +0200487 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
488 "RTCPSender::PLI");
489 ++packet_type_counter_.pli_packets;
490 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
491 ssrc_, packet_type_counter_.pli_packets);
492
danilchap56036ff2016-03-22 11:14:09 -0700493 return std::unique_ptr<rtcp::RtcpPacket>(pli);
Erik Språng61be2a42015-04-27 13:32:52 +0200494}
495
danilchap56036ff2016-03-22 11:14:09 -0700496std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildFIR(const RtcpContext& ctx) {
danilchap498ee8e2017-02-08 05:24:31 -0800497 ++sequence_number_fir_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000498
Erik Språngf7c57762015-12-04 10:40:35 +0100499 rtcp::Fir* fir = new rtcp::Fir();
danilchap822a16f2016-09-27 09:27:47 -0700500 fir->SetSenderSsrc(ssrc_);
501 fir->AddRequestTo(remote_ssrc_, sequence_number_fir_);
Erik Språng242e22b2015-05-11 10:17:43 +0200502
503 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
504 "RTCPSender::FIR");
505 ++packet_type_counter_.fir_packets;
506 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
507 ssrc_, packet_type_counter_.fir_packets);
508
danilchap56036ff2016-03-22 11:14:09 -0700509 return std::unique_ptr<rtcp::RtcpPacket>(fir);
niklase@google.com470e71d2011-07-07 08:21:25 +0000510}
511
danilchap56036ff2016-03-22 11:14:09 -0700512std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildREMB(
Erik Språngf7c57762015-12-04 10:40:35 +0100513 const RtcpContext& ctx) {
514 rtcp::Remb* remb = new rtcp::Remb();
danilchap822a16f2016-09-27 09:27:47 -0700515 remb->SetSenderSsrc(ssrc_);
516 remb->SetBitrateBps(remb_bitrate_);
517 remb->SetSsrcs(remb_ssrcs_);
Erik Språng61be2a42015-04-27 13:32:52 +0200518
Erik Språng242e22b2015-05-11 10:17:43 +0200519 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
520 "RTCPSender::REMB");
521
danilchap56036ff2016-03-22 11:14:09 -0700522 return std::unique_ptr<rtcp::RtcpPacket>(remb);
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000523}
524
Erik Språng61be2a42015-04-27 13:32:52 +0200525void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
danilchap56036ff2016-03-22 11:14:09 -0700526 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap2b616392016-08-18 06:17:42 -0700527 tmmbr_send_bps_ = target_bitrate;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000528}
529
danilchap56036ff2016-03-22 11:14:09 -0700530std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBR(
Erik Språngf7c57762015-12-04 10:40:35 +0100531 const RtcpContext& ctx) {
532 if (ctx.feedback_state_.module == nullptr)
533 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200534 // Before sending the TMMBR check the received TMMBN, only an owner is
535 // allowed to raise the bitrate:
536 // * If the sender is an owner of the TMMBN -> send TMMBR
537 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000538
Erik Språng61be2a42015-04-27 13:32:52 +0200539 // get current bounding set from RTCP receiver
danilchap2b616392016-08-18 06:17:42 -0700540 bool tmmbr_owner = false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000541
Erik Språng242e22b2015-05-11 10:17:43 +0200542 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
543 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
Erik Språng61be2a42015-04-27 13:32:52 +0200544 // since RTCPreceiver is not doing the reverse we should be fine
danilchap2b616392016-08-18 06:17:42 -0700545 std::vector<rtcp::TmmbItem> candidates =
546 ctx.feedback_state_.module->BoundingSet(&tmmbr_owner);
niklase@google.com470e71d2011-07-07 08:21:25 +0000547
danilchap2b616392016-08-18 06:17:42 -0700548 if (!candidates.empty()) {
549 for (const auto& candidate : candidates) {
550 if (candidate.bitrate_bps() == tmmbr_send_bps_ &&
551 candidate.packet_overhead() == packet_oh_send_) {
Erik Språngf7c57762015-12-04 10:40:35 +0100552 // Do not send the same tuple.
553 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200554 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000555 }
danilchap2b616392016-08-18 06:17:42 -0700556 if (!tmmbr_owner) {
557 // Use received bounding set as candidate set.
558 // Add current tuple.
559 candidates.emplace_back(ssrc_, tmmbr_send_bps_, packet_oh_send_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000560
danilchap2b616392016-08-18 06:17:42 -0700561 // Find bounding set.
danilchap2f69ce92016-08-16 03:21:38 -0700562 std::vector<rtcp::TmmbItem> bounding =
563 TMMBRHelp::FindBoundingSet(std::move(candidates));
danilchap2b616392016-08-18 06:17:42 -0700564 tmmbr_owner = TMMBRHelp::IsOwner(bounding, ssrc_);
565 if (!tmmbr_owner) {
Erik Språngf7c57762015-12-04 10:40:35 +0100566 // Did not enter bounding set, no meaning to send this request.
567 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200568 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000569 }
Erik Språng61be2a42015-04-27 13:32:52 +0200570 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000571
danilchap2b616392016-08-18 06:17:42 -0700572 if (!tmmbr_send_bps_)
Erik Språngf7c57762015-12-04 10:40:35 +0100573 return nullptr;
sprang81a3e602015-08-21 05:30:11 -0700574
Erik Språngf7c57762015-12-04 10:40:35 +0100575 rtcp::Tmmbr* tmmbr = new rtcp::Tmmbr();
danilchap822a16f2016-09-27 09:27:47 -0700576 tmmbr->SetSenderSsrc(ssrc_);
danilchapf174e3a2016-02-05 04:56:36 -0800577 rtcp::TmmbItem request;
578 request.set_ssrc(remote_ssrc_);
danilchap2b616392016-08-18 06:17:42 -0700579 request.set_bitrate_bps(tmmbr_send_bps_);
danilchapf174e3a2016-02-05 04:56:36 -0800580 request.set_packet_overhead(packet_oh_send_);
danilchap822a16f2016-09-27 09:27:47 -0700581 tmmbr->AddTmmbr(request);
Erik Språngf7c57762015-12-04 10:40:35 +0100582
danilchap56036ff2016-03-22 11:14:09 -0700583 return std::unique_ptr<rtcp::RtcpPacket>(tmmbr);
Erik Språng61be2a42015-04-27 13:32:52 +0200584}
585
danilchap56036ff2016-03-22 11:14:09 -0700586std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBN(
Erik Språngf7c57762015-12-04 10:40:35 +0100587 const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100588 rtcp::Tmmbn* tmmbn = new rtcp::Tmmbn();
danilchap822a16f2016-09-27 09:27:47 -0700589 tmmbn->SetSenderSsrc(ssrc_);
danilchap6eaa3a42016-05-09 10:59:50 -0700590 for (const rtcp::TmmbItem& tmmbr : tmmbn_to_send_) {
591 if (tmmbr.bitrate_bps() > 0) {
danilchap822a16f2016-09-27 09:27:47 -0700592 tmmbn->AddTmmbr(tmmbr);
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000593 }
Erik Språng61be2a42015-04-27 13:32:52 +0200594 }
sprangd83df502015-08-27 01:05:08 -0700595
danilchap56036ff2016-03-22 11:14:09 -0700596 return std::unique_ptr<rtcp::RtcpPacket>(tmmbn);
niklase@google.com470e71d2011-07-07 08:21:25 +0000597}
598
danilchap56036ff2016-03-22 11:14:09 -0700599std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildAPP(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100600 rtcp::App* app = new rtcp::App();
danilchap822a16f2016-09-27 09:27:47 -0700601 app->SetSsrc(ssrc_);
602 app->SetSubType(app_sub_type_);
603 app->SetName(app_name_);
604 app->SetData(app_data_.get(), app_length_);
Erik Språng521875a2015-09-01 10:11:16 +0200605
danilchap56036ff2016-03-22 11:14:09 -0700606 return std::unique_ptr<rtcp::RtcpPacket>(app);
Erik Språng61be2a42015-04-27 13:32:52 +0200607}
608
danilchap56036ff2016-03-22 11:14:09 -0700609std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildNACK(
Erik Språngf7c57762015-12-04 10:40:35 +0100610 const RtcpContext& ctx) {
611 rtcp::Nack* nack = new rtcp::Nack();
danilchap822a16f2016-09-27 09:27:47 -0700612 nack->SetSenderSsrc(ssrc_);
613 nack->SetMediaSsrc(remote_ssrc_);
614 nack->SetPacketIds(ctx.nack_list_, ctx.nack_size_);
Erik Språng61be2a42015-04-27 13:32:52 +0200615
616 // Report stats.
617 NACKStringBuilder stringBuilder;
Erik Språngf7c57762015-12-04 10:40:35 +0100618 for (int idx = 0; idx < ctx.nack_size_; ++idx) {
619 stringBuilder.PushNACK(ctx.nack_list_[idx]);
620 nack_stats_.ReportRequest(ctx.nack_list_[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +0200621 }
Erik Språng61be2a42015-04-27 13:32:52 +0200622 packet_type_counter_.nack_requests = nack_stats_.requests();
623 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +0200624
625 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
626 "RTCPSender::NACK", "nacks",
627 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
628 ++packet_type_counter_.nack_packets;
629 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
630 ssrc_, packet_type_counter_.nack_packets);
631
danilchap56036ff2016-03-22 11:14:09 -0700632 return std::unique_ptr<rtcp::RtcpPacket>(nack);
Erik Språng61be2a42015-04-27 13:32:52 +0200633}
634
danilchap56036ff2016-03-22 11:14:09 -0700635std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildBYE(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100636 rtcp::Bye* bye = new rtcp::Bye();
danilchap822a16f2016-09-27 09:27:47 -0700637 bye->SetSenderSsrc(ssrc_);
638 bye->SetCsrcs(csrcs_);
sprangd8ee4f92015-08-24 03:25:19 -0700639
danilchap56036ff2016-03-22 11:14:09 -0700640 return std::unique_ptr<rtcp::RtcpPacket>(bye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000641}
642
sprang5e38c962016-12-01 05:18:09 -0800643std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildExtendedReports(
Erik Språngf7c57762015-12-04 10:40:35 +0100644 const RtcpContext& ctx) {
sprang5e38c962016-12-01 05:18:09 -0800645 std::unique_ptr<rtcp::ExtendedReports> xr(new rtcp::ExtendedReports());
danilchap822a16f2016-09-27 09:27:47 -0700646 xr->SetSenderSsrc(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000647
sprang5e38c962016-12-01 05:18:09 -0800648 if (!sending_ && xr_send_receiver_reference_time_enabled_) {
649 rtcp::Rrtr rrtr;
danilchap51813b32016-12-16 02:44:36 -0800650 rrtr.SetNtp(ctx.now_);
sprang5e38c962016-12-01 05:18:09 -0800651 xr->SetRrtr(rrtr);
652 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000653
sprang5e38c962016-12-01 05:18:09 -0800654 if (ctx.feedback_state_.has_last_xr_rr) {
655 xr->AddDlrrItem(ctx.feedback_state_.last_xr_rr);
656 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000657
sprang5e38c962016-12-01 05:18:09 -0800658 if (video_bitrate_allocation_) {
659 rtcp::TargetBitrate target_bitrate;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000660
sprang5e38c962016-12-01 05:18:09 -0800661 for (int sl = 0; sl < kMaxSpatialLayers; ++sl) {
662 for (int tl = 0; tl < kMaxTemporalStreams; ++tl) {
663 uint32_t layer_bitrate_bps =
664 video_bitrate_allocation_->GetBitrate(sl, tl);
665 if (layer_bitrate_bps > 0)
666 target_bitrate.AddTargetBitrate(sl, tl, layer_bitrate_bps / 1000);
667 }
668 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000669
sprang5e38c962016-12-01 05:18:09 -0800670 xr->SetTargetBitrate(target_bitrate);
671 video_bitrate_allocation_.reset();
672 }
Erik Språngca28fdc2015-08-31 14:00:50 +0200673
sprang5e38c962016-12-01 05:18:09 -0800674 if (xr_voip_metric_) {
675 rtcp::VoipMetric voip;
676 voip.SetMediaSsrc(remote_ssrc_);
677 voip.SetVoipMetric(*xr_voip_metric_);
678 xr_voip_metric_.reset();
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000679
sprang5e38c962016-12-01 05:18:09 -0800680 xr->SetVoipMetric(voip);
681 }
Erik Språngca28fdc2015-08-31 14:00:50 +0200682
sprang5e38c962016-12-01 05:18:09 -0800683 return std::move(xr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000684}
685
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000686int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200687 RTCPPacketType packetType,
688 int32_t nack_size,
nissecd386eb2017-03-14 08:54:43 -0700689 const uint16_t* nack_list) {
Erik Språng242e22b2015-05-11 10:17:43 +0200690 return SendCompoundRTCP(
691 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
nissecd386eb2017-03-14 08:54:43 -0700692 nack_size, nack_list);
Erik Språng242e22b2015-05-11 10:17:43 +0200693}
694
695int32_t RTCPSender::SendCompoundRTCP(
696 const FeedbackState& feedback_state,
Erik Språngf7c57762015-12-04 10:40:35 +0100697 const std::set<RTCPPacketType>& packet_types,
Erik Språng242e22b2015-05-11 10:17:43 +0200698 int32_t nack_size,
nissecd386eb2017-03-14 08:54:43 -0700699 const uint16_t* nack_list) {
terelius429c3452016-01-21 05:42:04 -0800700 PacketContainer container(transport_, event_log_);
nisse6f142eb2017-02-21 07:32:47 -0800701 size_t max_packet_size;
702
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000703 {
danilchap56036ff2016-03-22 11:14:09 -0700704 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbosda903ea2015-10-02 02:36:56 -0700705 if (method_ == RtcpMode::kOff) {
Erik Språng61be2a42015-04-27 13:32:52 +0200706 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
707 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +0000708 }
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200709 // Add all flags as volatile. Non volatile entries will not be overwritten.
710 // All new volatile flags added will be consumed by the end of this call.
711 SetFlags(packet_types, true);
712
713 // Prevent sending streams to send SR before any media has been sent.
714 const bool can_calculate_rtp_timestamp = (last_frame_capture_time_ms_ >= 0);
715 if (!can_calculate_rtp_timestamp) {
716 bool consumed_sr_flag = ConsumeFlag(kRtcpSr);
717 bool consumed_report_flag = sending_ && ConsumeFlag(kRtcpReport);
718 bool sender_report = consumed_report_flag || consumed_sr_flag;
719 if (sender_report && AllVolatileFlagsConsumed()) {
720 // This call was for Sender Report and nothing else.
721 return 0;
722 }
723 if (sending_ && method_ == RtcpMode::kCompound) {
724 // Not allowed to send any RTCP packet without sender report.
725 return -1;
726 }
727 }
728
729 if (packet_type_counter_.first_packet_time_ms == -1)
730 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språngf7c57762015-12-04 10:40:35 +0100731
732 // We need to send our NTP even if we haven't received any reports.
nissecd386eb2017-03-14 08:54:43 -0700733 RtcpContext context(feedback_state, nack_size, nack_list,
danilchap37953762017-02-09 11:15:25 -0800734 clock_->CurrentNtpTime());
Erik Språngf7c57762015-12-04 10:40:35 +0100735
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200736 PrepareReport(feedback_state);
Erik Språngf7c57762015-12-04 10:40:35 +0100737
danilchap56036ff2016-03-22 11:14:09 -0700738 std::unique_ptr<rtcp::RtcpPacket> packet_bye;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800739
Erik Språngf7c57762015-12-04 10:40:35 +0100740 auto it = report_flags_.begin();
741 while (it != report_flags_.end()) {
742 auto builder_it = builders_.find(it->type);
sprang5e38c962016-12-01 05:18:09 -0800743 RTC_DCHECK(builder_it != builders_.end())
744 << "Could not find builder for packet type " << it->type;
Erik Språngf7c57762015-12-04 10:40:35 +0100745 if (it->is_volatile) {
746 report_flags_.erase(it++);
747 } else {
748 ++it;
749 }
750
751 BuilderFunc func = builder_it->second;
danilchap56036ff2016-03-22 11:14:09 -0700752 std::unique_ptr<rtcp::RtcpPacket> packet = (this->*func)(context);
Erik Språngf7c57762015-12-04 10:40:35 +0100753 if (packet.get() == nullptr)
754 return -1;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800755 // If there is a BYE, don't append now - save it and append it
756 // at the end later.
757 if (builder_it->first == kRtcpBye) {
758 packet_bye = std::move(packet);
759 } else {
760 container.Append(packet.release());
761 }
762 }
763
764 // Append the BYE now at the end
765 if (packet_bye) {
766 container.Append(packet_bye.release());
Erik Språngf7c57762015-12-04 10:40:35 +0100767 }
768
769 if (packet_type_counter_observer_ != nullptr) {
770 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
771 remote_ssrc_, packet_type_counter_);
772 }
773
774 RTC_DCHECK(AllVolatileFlagsConsumed());
nisse6f142eb2017-02-21 07:32:47 -0800775 max_packet_size = max_packet_size_;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000776 }
Erik Språng61be2a42015-04-27 13:32:52 +0200777
nisse6f142eb2017-02-21 07:32:47 -0800778 size_t bytes_sent = container.SendPackets(max_packet_size);
Erik Språngf7c57762015-12-04 10:40:35 +0100779 return bytes_sent == 0 ? -1 : 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000780}
781
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200782void RTCPSender::PrepareReport(const FeedbackState& feedback_state) {
Erik Språng242e22b2015-05-11 10:17:43 +0200783 bool generate_report;
784 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
785 // Report type already explicitly set, don't automatically populate.
786 generate_report = true;
henrikg91d6ede2015-09-17 00:24:34 -0700787 RTC_DCHECK(ConsumeFlag(kRtcpReport) == false);
Erik Språng242e22b2015-05-11 10:17:43 +0200788 } else {
789 generate_report =
pbosda903ea2015-10-02 02:36:56 -0700790 (ConsumeFlag(kRtcpReport) && method_ == RtcpMode::kReducedSize) ||
791 method_ == RtcpMode::kCompound;
Erik Språng242e22b2015-05-11 10:17:43 +0200792 if (generate_report)
793 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000794 }
795
Erik Språng0ea42d32015-06-25 14:46:16 +0200796 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
Erik Språng242e22b2015-05-11 10:17:43 +0200797 SetFlag(kRtcpSdes, true);
798
Erik Språng242e22b2015-05-11 10:17:43 +0200799 if (generate_report) {
sprang5e38c962016-12-01 05:18:09 -0800800 if ((!sending_ && xr_send_receiver_reference_time_enabled_) ||
801 feedback_state.has_last_xr_rr || video_bitrate_allocation_) {
802 SetFlag(kRtcpAnyExtendedReports, true);
803 }
Erik Språng242e22b2015-05-11 10:17:43 +0200804
805 // generate next time to send an RTCP report
danilchap47a740b2015-12-15 00:30:07 -0800806 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000807
danilchap47a740b2015-12-15 00:30:07 -0800808 if (!audio_) {
Erik Språng242e22b2015-05-11 10:17:43 +0200809 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200810 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
811 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
812 if (send_bitrate_kbit != 0)
813 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000814 }
Erik Språng61be2a42015-04-27 13:32:52 +0200815 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
816 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
Erik Språng61be2a42015-04-27 13:32:52 +0200817 }
danilchap47a740b2015-12-15 00:30:07 -0800818 // The interval between RTCP packets is varied randomly over the
819 // range [1/2,3/2] times the calculated interval.
820 uint32_t timeToNext =
821 random_.Rand(minIntervalMs * 1 / 2, minIntervalMs * 3 / 2);
Erik Språng242e22b2015-05-11 10:17:43 +0200822 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000823
Per83d09102016-04-15 14:59:13 +0200824 if (receive_statistics_) {
825 StatisticianMap statisticians =
826 receive_statistics_->GetActiveStatisticians();
827 RTC_DCHECK(report_blocks_.empty());
828 for (auto& it : statisticians) {
829 AddReportBlock(feedback_state, it.first, it.second);
830 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000831 }
832 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000833}
834
danilchapa72e7342015-12-22 08:07:45 -0800835bool RTCPSender::AddReportBlock(const FeedbackState& feedback_state,
836 uint32_t ssrc,
837 StreamStatistician* statistician) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000838 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000839 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000840 if (!statistician->GetStatistics(&stats, true))
841 return false;
danilchapa72e7342015-12-22 08:07:45 -0800842
843 if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) {
844 LOG(LS_WARNING) << "Too many report blocks.";
845 return false;
846 }
847 RTC_DCHECK(report_blocks_.find(ssrc) == report_blocks_.end());
848 rtcp::ReportBlock* block = &report_blocks_[ssrc];
danilchap822a16f2016-09-27 09:27:47 -0700849 block->SetMediaSsrc(ssrc);
850 block->SetFractionLost(stats.fraction_lost);
851 if (!block->SetCumulativeLost(stats.cumulative_lost)) {
danilchapa72e7342015-12-22 08:07:45 -0800852 report_blocks_.erase(ssrc);
853 LOG(LS_WARNING) << "Cumulative lost is oversized.";
854 return false;
855 }
danilchap822a16f2016-09-27 09:27:47 -0700856 block->SetExtHighestSeqNum(stats.extended_max_sequence_number);
857 block->SetJitter(stats.jitter);
858 block->SetLastSr(feedback_state.remote_sr);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000859
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200860 // TODO(sprang): Do we really need separate time stamps for each report?
861 // Get our NTP as late as possible to avoid a race.
danilchap42287842017-02-20 06:40:18 -0800862 NtpTime ntp = clock_->CurrentNtpTime();
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000863
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200864 // Delay since last received report.
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000865 if ((feedback_state.last_rr_ntp_secs != 0) ||
866 (feedback_state.last_rr_ntp_frac != 0)) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200867 // Get the 16 lowest bits of seconds and the 16 highest bits of fractions.
danilchap42287842017-02-20 06:40:18 -0800868 uint32_t now = CompactNtp(ntp);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000869
Erik Språng61be2a42015-04-27 13:32:52 +0200870 uint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
871 receiveTime <<= 16;
872 receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000873
danilchap822a16f2016-09-27 09:27:47 -0700874 block->SetDelayLastSr(now - receiveTime);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000875 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000876 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000877}
878
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000879void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
kwiberg352444f2016-11-28 15:58:53 -0800880 RTC_DCHECK_LE(csrcs.size(), kRtpCsrcSize);
danilchap56036ff2016-03-22 11:14:09 -0700881 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000882 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +0000883}
884
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000885int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
886 uint32_t name,
887 const uint8_t* data,
888 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +0200889 if (length % 4 != 0) {
890 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
891 return -1;
892 }
danilchap56036ff2016-03-22 11:14:09 -0700893 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000894
Erik Språng242e22b2015-05-11 10:17:43 +0200895 SetFlag(kRtcpApp, true);
896 app_sub_type_ = subType;
897 app_name_ = name;
898 app_data_.reset(new uint8_t[length]);
899 app_length_ = length;
900 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +0200901 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000902}
903
spranga790d832016-12-02 07:29:44 -0800904// TODO(sprang): Remove support for VoIP metrics? (Not used in receiver.)
Erik Språng61be2a42015-04-27 13:32:52 +0200905int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
danilchap56036ff2016-03-22 11:14:09 -0700906 rtc::CritScope lock(&critical_section_rtcp_sender_);
sprang5e38c962016-12-01 05:18:09 -0800907 xr_voip_metric_.emplace(*VoIPMetric);
niklase@google.com470e71d2011-07-07 08:21:25 +0000908
sprang5e38c962016-12-01 05:18:09 -0800909 SetFlag(kRtcpAnyExtendedReports, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200910 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000911}
912
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000913void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700914 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200915 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000916}
917
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000918bool RTCPSender::RtcpXrReceiverReferenceTime() const {
danilchap56036ff2016-03-22 11:14:09 -0700919 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200920 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000921}
922
danilchap853ecb22016-08-22 08:26:15 -0700923void RTCPSender::SetTmmbn(std::vector<rtcp::TmmbItem> bounding_set) {
danilchap56036ff2016-03-22 11:14:09 -0700924 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap853ecb22016-08-22 08:26:15 -0700925 tmmbn_to_send_ = std::move(bounding_set);
danilchap6eaa3a42016-05-09 10:59:50 -0700926 SetFlag(kRtcpTmmbn, true);
niklase@google.com470e71d2011-07-07 08:21:25 +0000927}
Erik Språng61be2a42015-04-27 13:32:52 +0200928
sprang5e38c962016-12-01 05:18:09 -0800929void RTCPSender::SetFlag(uint32_t type, bool is_volatile) {
930 if (type & kRtcpAnyExtendedReports) {
931 report_flags_.insert(ReportFlag(kRtcpAnyExtendedReports, is_volatile));
932 } else {
933 report_flags_.insert(ReportFlag(type, is_volatile));
934 }
Erik Språng242e22b2015-05-11 10:17:43 +0200935}
936
937void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
938 bool is_volatile) {
939 for (RTCPPacketType type : types)
940 SetFlag(type, is_volatile);
941}
942
sprang5e38c962016-12-01 05:18:09 -0800943bool RTCPSender::IsFlagPresent(uint32_t type) const {
Erik Språng242e22b2015-05-11 10:17:43 +0200944 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
945}
946
sprang5e38c962016-12-01 05:18:09 -0800947bool RTCPSender::ConsumeFlag(uint32_t type, bool forced) {
Erik Språng242e22b2015-05-11 10:17:43 +0200948 auto it = report_flags_.find(ReportFlag(type, false));
949 if (it == report_flags_.end())
950 return false;
951 if (it->is_volatile || forced)
952 report_flags_.erase((it));
953 return true;
954}
955
956bool RTCPSender::AllVolatileFlagsConsumed() const {
957 for (const ReportFlag& flag : report_flags_) {
958 if (flag.is_volatile)
959 return false;
960 }
961 return true;
962}
963
sprang5e38c962016-12-01 05:18:09 -0800964void RTCPSender::SetVideoBitrateAllocation(const BitrateAllocation& bitrate) {
965 rtc::CritScope lock(&critical_section_rtcp_sender_);
966 video_bitrate_allocation_.emplace(bitrate);
967 SetFlag(kRtcpAnyExtendedReports, true);
968}
969
sprang233bd872015-09-08 13:25:16 -0700970bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
sprang233bd872015-09-08 13:25:16 -0700971 class Sender : public rtcp::RtcpPacket::PacketReadyCallback {
972 public:
terelius429c3452016-01-21 05:42:04 -0800973 Sender(Transport* transport, RtcEventLog* event_log)
974 : transport_(transport), event_log_(event_log), send_failure_(false) {}
sprang233bd872015-09-08 13:25:16 -0700975
976 void OnPacketReady(uint8_t* data, size_t length) override {
terelius429c3452016-01-21 05:42:04 -0800977 if (transport_->SendRtcp(data, length)) {
978 if (event_log_) {
979 event_log_->LogRtcpPacket(kOutgoingPacket, MediaType::ANY, data,
980 length);
981 }
982 } else {
sprang233bd872015-09-08 13:25:16 -0700983 send_failure_ = true;
terelius429c3452016-01-21 05:42:04 -0800984 }
sprang233bd872015-09-08 13:25:16 -0700985 }
986
987 Transport* const transport_;
terelius429c3452016-01-21 05:42:04 -0800988 RtcEventLog* const event_log_;
sprang233bd872015-09-08 13:25:16 -0700989 bool send_failure_;
terelius429c3452016-01-21 05:42:04 -0800990 // TODO(terelius): We would like to
991 // RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(Sender);
992 // but we can't because of an incorrect warning (C4822) in MVS 2013.
993 } sender(transport_, event_log_);
sprang233bd872015-09-08 13:25:16 -0700994
nisse6f142eb2017-02-21 07:32:47 -0800995 size_t max_packet_size;
stefanb77c7162017-02-06 06:29:38 -0800996 {
997 rtc::CritScope lock(&critical_section_rtcp_sender_);
998 if (method_ == RtcpMode::kOff)
999 return false;
nisse6f142eb2017-02-21 07:32:47 -08001000 max_packet_size = max_packet_size_;
stefanb77c7162017-02-06 06:29:38 -08001001 }
1002
nisse6f142eb2017-02-21 07:32:47 -08001003 RTC_DCHECK_LE(max_packet_size, IP_PACKET_SIZE);
sprang233bd872015-09-08 13:25:16 -07001004 uint8_t buffer[IP_PACKET_SIZE];
nisse6f142eb2017-02-21 07:32:47 -08001005 return packet.BuildExternalBuffer(buffer, max_packet_size, &sender) &&
sprang233bd872015-09-08 13:25:16 -07001006 !sender.send_failure_;
1007}
1008
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001009} // namespace webrtc