blob: 08858e2f6a84c68f186f302ec7888fb725f4060a [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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/rtp_rtcp/source/rtp_sender.h"
pwestin@webrtc.org571a1c02012-11-13 21:12:39 +000012
danilchapb8b6fbb2015-12-10 05:05:27 -080013#include <algorithm>
Johannes Kron965e7942018-09-13 15:36:20 +020014#include <limits>
Steve Anton296a0ce2018-03-22 15:17:27 -070015#include <string>
Shao Changbine62202f2015-04-21 20:24:50 +080016#include <utility>
niklase@google.com470e71d2011-07-07 08:21:25 +000017
Karl Wiberg918f50c2018-07-05 11:40:33 +020018#include "absl/memory/memory.h"
Niels Mölleraa3c1cc2018-11-02 10:54:56 +010019#include "absl/strings/match.h"
Amit Hilbuch77938e62018-12-21 09:23:38 -080020#include "api/array_view.h"
Danil Chapovalov83bbe912019-08-07 12:24:53 +020021#include "api/rtc_event_log/rtc_event_log.h"
Erik Språng4580ca22019-07-04 10:38:43 +020022#include "api/transport/field_trial_based_config.h"
Elad Alon4a87e1c2017-10-03 16:11:34 +020023#include "logging/rtc_event_log/events/rtc_event_rtp_packet_outgoing.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020024#include "modules/rtp_rtcp/include/rtp_cvo.h"
25#include "modules/rtp_rtcp/source/byte_io.h"
philipel569397f2018-09-26 12:25:31 +020026#include "modules/rtp_rtcp/source/rtp_generic_frame_descriptor_extension.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020027#include "modules/rtp_rtcp/source/rtp_header_extensions.h"
28#include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020029#include "modules/rtp_rtcp/source/time_util.h"
30#include "rtc_base/arraysize.h"
31#include "rtc_base/checks.h"
32#include "rtc_base/logging.h"
Karl Wiberge40468b2017-11-22 10:42:26 +010033#include "rtc_base/numerics/safe_minmax.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020034#include "rtc_base/rate_limiter.h"
Steve Anton10542f22019-01-11 09:11:00 -080035#include "rtc_base/time_utils.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000036
37namespace webrtc {
niklase@google.com470e71d2011-07-07 08:21:25 +000038
hclam@chromium.org806dc3b2013-04-09 19:54:10 +000039namespace {
Danil Chapovalov31e4e802016-08-03 18:27:40 +020040// Max in the RFC 3550 is 255 bytes, we limit it to be modulus 32 for SRTP.
41constexpr size_t kMaxPaddingLength = 224;
stefan53b6cc32017-02-03 08:13:57 -080042constexpr size_t kMinAudioPaddingLength = 50;
Danil Chapovalov31e4e802016-08-03 18:27:40 +020043constexpr int kSendSideDelayWindowMs = 1000;
44constexpr size_t kRtpHeaderLength = 12;
45constexpr uint16_t kMaxInitRtpSeqNumber = 32767; // 2^15 -1.
46constexpr uint32_t kTimestampTicksPerMs = 90;
47constexpr int kBitrateStatisticsWindowMs = 1000;
guoweis@webrtc.org45362892015-03-04 22:55:15 +000048
Erik Språng214f5432019-06-20 15:09:58 +020049// Min size needed to get payload padding from packet history.
50constexpr int kMinPayloadPaddingBytes = 50;
51
erikvarga27883732017-05-17 05:08:38 -070052template <typename Extension>
53constexpr RtpExtensionSize CreateExtensionSize() {
54 return {Extension::kId, Extension::kValueSizeBytes};
55}
56
Amit Hilbuch77938e62018-12-21 09:23:38 -080057template <typename Extension>
58constexpr RtpExtensionSize CreateMaxExtensionSize() {
59 return {Extension::kId, Extension::kMaxValueSizeBytes};
60}
61
erikvarga27883732017-05-17 05:08:38 -070062// Size info for header extensions that might be used in padding or FEC packets.
Ilya Nikolaevskiy1d037ae2018-03-15 15:46:17 +010063constexpr RtpExtensionSize kFecOrPaddingExtensionSizes[] = {
erikvarga27883732017-05-17 05:08:38 -070064 CreateExtensionSize<AbsoluteSendTime>(),
65 CreateExtensionSize<TransmissionOffset>(),
66 CreateExtensionSize<TransportSequenceNumber>(),
67 CreateExtensionSize<PlayoutDelayLimits>(),
Amit Hilbuch77938e62018-12-21 09:23:38 -080068 CreateMaxExtensionSize<RtpMid>(),
erikvarga27883732017-05-17 05:08:38 -070069};
70
Ilya Nikolaevskiy1d037ae2018-03-15 15:46:17 +010071// Size info for header extensions that might be used in video packets.
72constexpr RtpExtensionSize kVideoExtensionSizes[] = {
73 CreateExtensionSize<AbsoluteSendTime>(),
Chen Xingcd8a6e22019-07-01 10:56:51 +020074 CreateExtensionSize<AbsoluteCaptureTimeExtension>(),
Ilya Nikolaevskiy1d037ae2018-03-15 15:46:17 +010075 CreateExtensionSize<TransmissionOffset>(),
76 CreateExtensionSize<TransportSequenceNumber>(),
77 CreateExtensionSize<PlayoutDelayLimits>(),
78 CreateExtensionSize<VideoOrientation>(),
79 CreateExtensionSize<VideoContentTypeExtension>(),
80 CreateExtensionSize<VideoTimingExtension>(),
Amit Hilbuch77938e62018-12-21 09:23:38 -080081 CreateMaxExtensionSize<RtpStreamId>(),
82 CreateMaxExtensionSize<RepairedRtpStreamId>(),
83 CreateMaxExtensionSize<RtpMid>(),
Elad Alonccb9b752019-02-19 13:01:31 +010084 {RtpGenericFrameDescriptorExtension00::kId,
85 RtpGenericFrameDescriptorExtension00::kMaxSizeBytes},
86 {RtpGenericFrameDescriptorExtension01::kId,
87 RtpGenericFrameDescriptorExtension01::kMaxSizeBytes},
Ilya Nikolaevskiy1d037ae2018-03-15 15:46:17 +010088};
89
Erik Språng4580ca22019-07-04 10:38:43 +020090bool IsEnabled(absl::string_view name,
91 const WebRtcKeyValueConfig* field_trials) {
92 FieldTrialBasedConfig default_trials;
93 auto& trials = field_trials ? *field_trials : default_trials;
94 return trials.Lookup(name).find("Enabled") == 0;
95}
96
Mirko Bonadei999a72a2019-07-12 17:33:46 +000097bool HasBweExtension(const RtpHeaderExtensionMap& extensions_map) {
98 return extensions_map.IsRegistered(kRtpExtensionTransportSequenceNumber) ||
99 extensions_map.IsRegistered(kRtpExtensionTransportSequenceNumber02) ||
100 extensions_map.IsRegistered(kRtpExtensionAbsoluteSendTime) ||
101 extensions_map.IsRegistered(kRtpExtensionTransmissionTimeOffset);
102}
103
hclam@chromium.org806dc3b2013-04-09 19:54:10 +0000104} // namespace
105
Erik Språng4580ca22019-07-04 10:38:43 +0200106RTPSender::RTPSender(const RtpRtcp::Configuration& config)
107 : clock_(config.clock),
108 random_(clock_->TimeInMicroseconds()),
109 audio_configured_(config.audio),
110 flexfec_ssrc_(config.flexfec_sender
111 ? absl::make_optional(config.flexfec_sender->ssrc())
112 : absl::nullopt),
113 paced_sender_(config.paced_sender),
114 transport_sequence_number_allocator_(
115 config.transport_sequence_number_allocator),
116 transport_feedback_observer_(config.transport_feedback_callback),
117 transport_(config.outgoing_transport),
118 sending_media_(true), // Default to sending media.
119 force_part_of_allocation_(false),
120 max_packet_size_(IP_PACKET_SIZE - 28), // Default is IP-v4/UDP.
121 last_payload_type_(-1),
122 rtp_header_extension_map_(config.extmap_allow_mixed),
123 packet_history_(clock_),
Erik Språng4580ca22019-07-04 10:38:43 +0200124 // Statistics
125 send_delays_(),
126 max_delay_it_(send_delays_.end()),
127 sum_delays_ms_(0),
128 total_packet_send_delay_ms_(0),
129 rtp_stats_callback_(nullptr),
130 total_bitrate_sent_(kBitrateStatisticsWindowMs,
131 RateStatistics::kBpsScale),
132 nack_bitrate_sent_(kBitrateStatisticsWindowMs, RateStatistics::kBpsScale),
133 send_side_delay_observer_(config.send_side_delay_observer),
134 event_log_(config.event_log),
135 send_packet_observer_(config.send_packet_observer),
136 bitrate_callback_(config.send_bitrate_observer),
137 // RTP variables
138 sequence_number_forced_(false),
Erik Språng54d5d2c2019-08-20 17:22:36 +0200139 ssrc_(config.get_local_media_ssrc()),
Steve Anton2bac7da2019-07-21 15:04:21 -0400140 ssrc_has_acked_(false),
141 rtx_ssrc_has_acked_(false),
Erik Språng4580ca22019-07-04 10:38:43 +0200142 last_rtp_timestamp_(0),
143 capture_time_ms_(0),
144 last_timestamp_time_ms_(0),
145 media_has_been_sent_(false),
146 last_packet_marker_bit_(false),
147 csrcs_(),
148 rtx_(kRtxOff),
149 ssrc_rtx_(config.rtx_send_ssrc),
150 rtp_overhead_bytes_per_packet_(0),
Mirko Bonadei999a72a2019-07-12 17:33:46 +0000151 supports_bwe_extension_(false),
Erik Språng4580ca22019-07-04 10:38:43 +0200152 retransmission_rate_limiter_(config.retransmission_rate_limiter),
153 overhead_observer_(config.overhead_observer),
154 populate_network2_timestamp_(config.populate_network2_timestamp),
155 send_side_bwe_with_overhead_(
Erik Språngf5815fa2019-08-21 14:27:31 +0200156 IsEnabled("WebRTC-SendSideBwe-WithOverhead", config.field_trials)) {
Erik Språng4580ca22019-07-04 10:38:43 +0200157 // This random initialization is not intended to be cryptographic strong.
158 timestamp_offset_ = random_.Rand<uint32_t>();
159 // Random start, 16 bits. Can't be 0.
160 sequence_number_rtx_ = random_.Rand(1, kMaxInitRtpSeqNumber);
161 sequence_number_ = random_.Rand(1, kMaxInitRtpSeqNumber);
Erik Språng4580ca22019-07-04 10:38:43 +0200162}
163
Amit Hilbuch02d7d352019-07-02 21:04:57 +0000164RTPSender::RTPSender(
165 bool audio,
166 Clock* clock,
167 Transport* transport,
Erik Språngaa59eca2019-07-24 14:52:55 +0200168 RtpPacketSender* paced_sender,
Amit Hilbuch02d7d352019-07-02 21:04:57 +0000169 absl::optional<uint32_t> flexfec_ssrc,
170 TransportSequenceNumberAllocator* sequence_number_allocator,
171 TransportFeedbackObserver* transport_feedback_observer,
172 BitrateStatisticsObserver* bitrate_callback,
173 SendSideDelayObserver* send_side_delay_observer,
174 RtcEventLog* event_log,
175 SendPacketObserver* send_packet_observer,
176 RateLimiter* retransmission_rate_limiter,
177 OverheadObserver* overhead_observer,
178 bool populate_network2_timestamp,
179 FrameEncryptorInterface* frame_encryptor,
180 bool require_frame_encryption,
181 bool extmap_allow_mixed,
182 const WebRtcKeyValueConfig& field_trials)
183 : clock_(clock),
danilchap47a740b2015-12-15 00:30:07 -0800184 random_(clock_->TimeInMicroseconds()),
Amit Hilbuch02d7d352019-07-02 21:04:57 +0000185 audio_configured_(audio),
186 flexfec_ssrc_(flexfec_ssrc),
187 paced_sender_(paced_sender),
188 transport_sequence_number_allocator_(sequence_number_allocator),
189 transport_feedback_observer_(transport_feedback_observer),
190 transport_(transport),
Sebastian Jansson1bca65b2018-10-10 09:58:08 +0200191 sending_media_(true), // Default to sending media.
192 force_part_of_allocation_(false),
nisse284542b2017-01-10 08:58:32 -0800193 max_packet_size_(IP_PACKET_SIZE - 28), // Default is IP-v4/UDP.
Danil Chapovalovb3179c72018-03-22 10:13:07 +0100194 last_payload_type_(-1),
Amit Hilbuch02d7d352019-07-02 21:04:57 +0000195 rtp_header_extension_map_(extmap_allow_mixed),
196 packet_history_(clock),
phoglund@webrtc.org43da54a2013-01-25 10:53:38 +0000197 // Statistics
Johannes Kron4a8a5e72018-09-26 09:57:48 +0200198 send_delays_(),
199 max_delay_it_(send_delays_.end()),
200 sum_delays_ms_(0),
Henrik Boström9fe18342019-05-16 18:38:20 +0200201 total_packet_send_delay_ms_(0),
sprangcd349d92016-07-13 09:11:28 -0700202 rtp_stats_callback_(nullptr),
203 total_bitrate_sent_(kBitrateStatisticsWindowMs,
204 RateStatistics::kBpsScale),
205 nack_bitrate_sent_(kBitrateStatisticsWindowMs, RateStatistics::kBpsScale),
Amit Hilbuch02d7d352019-07-02 21:04:57 +0000206 send_side_delay_observer_(send_side_delay_observer),
207 event_log_(event_log),
208 send_packet_observer_(send_packet_observer),
209 bitrate_callback_(bitrate_callback),
sprang@webrtc.orgebad7652013-12-05 14:29:02 +0000210 // RTP variables
sprang@webrtc.org6811b6e2013-12-13 09:46:59 +0000211 sequence_number_forced_(false),
Steve Anton2bac7da2019-07-21 15:04:21 -0400212 ssrc_has_acked_(false),
213 rtx_ssrc_has_acked_(false),
danilchape5b41412016-08-22 03:39:23 -0700214 last_rtp_timestamp_(0),
sprang@webrtc.org6811b6e2013-12-13 09:46:59 +0000215 capture_time_ms_(0),
216 last_timestamp_time_ms_(0),
stefan@webrtc.org8b94e3d2014-07-17 16:10:14 +0000217 media_has_been_sent_(false),
sprang@webrtc.org6811b6e2013-12-13 09:46:59 +0000218 last_packet_marker_bit_(false),
sprang@webrtc.org6811b6e2013-12-13 09:46:59 +0000219 csrcs_(),
sprang@webrtc.org6811b6e2013-12-13 09:46:59 +0000220 rtx_(kRtxOff),
michaelt4da30442016-11-17 01:38:43 -0800221 rtp_overhead_bytes_per_packet_(0),
Mirko Bonadei999a72a2019-07-12 17:33:46 +0000222 supports_bwe_extension_(false),
Amit Hilbuch02d7d352019-07-02 21:04:57 +0000223 retransmission_rate_limiter_(retransmission_rate_limiter),
224 overhead_observer_(overhead_observer),
225 populate_network2_timestamp_(populate_network2_timestamp),
elad.alonc3dfff32017-01-26 02:46:55 -0800226 send_side_bwe_with_overhead_(
Amit Hilbuch02d7d352019-07-02 21:04:57 +0000227 field_trials.Lookup("WebRTC-SendSideBwe-WithOverhead")
Erik Språngc4f047d2019-07-19 13:34:11 +0200228 .find("Enabled") == 0) {
danilchap71fead22016-08-18 02:01:49 -0700229 // This random initialization is not intended to be cryptographic strong.
230 timestamp_offset_ = random_.Rand<uint32_t>();
mikhal@webrtc.orgbda7f302013-03-15 23:21:52 +0000231 // Random start, 16 bits. Can't be 0.
danilchap47a740b2015-12-15 00:30:07 -0800232 sequence_number_rtx_ = random_.Rand(1, kMaxInitRtpSeqNumber);
233 sequence_number_ = random_.Rand(1, kMaxInitRtpSeqNumber);
niklase@google.com470e71d2011-07-07 08:21:25 +0000234}
235
pwestin@webrtc.org00741872012-01-19 15:56:10 +0000236RTPSender::~RTPSender() {
tommiae695e92016-02-02 08:31:45 -0800237 // TODO(tommi): Use a thread checker to ensure the object is created and
238 // deleted on the same thread. At the moment this isn't possible due to
239 // voe::ChannelOwner in voice engine. To reproduce, run:
240 // voe_auto_test --automated --gtest_filter=*MixManyChannelsForStressOpus
241
242 // TODO(tommi,holmer): We don't grab locks in the dtor before accessing member
243 // variables but we grab them in all other methods. (what's the design?)
244 // Start documenting what thread we're on in what method so that it's easier
245 // to understand performance attributes and possibly remove locks.
niklase@google.com470e71d2011-07-07 08:21:25 +0000246}
niklase@google.com470e71d2011-07-07 08:21:25 +0000247
erikvarga27883732017-05-17 05:08:38 -0700248rtc::ArrayView<const RtpExtensionSize> RTPSender::FecExtensionSizes() {
Ilya Nikolaevskiy1d037ae2018-03-15 15:46:17 +0100249 return rtc::MakeArrayView(kFecOrPaddingExtensionSizes,
250 arraysize(kFecOrPaddingExtensionSizes));
251}
252
253rtc::ArrayView<const RtpExtensionSize> RTPSender::VideoExtensionSizes() {
254 return rtc::MakeArrayView(kVideoExtensionSizes,
255 arraysize(kVideoExtensionSizes));
erikvarga27883732017-05-17 05:08:38 -0700256}
257
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000258uint16_t RTPSender::ActualSendBitrateKbit() const {
sprangcd349d92016-07-13 09:11:28 -0700259 rtc::CritScope cs(&statistics_crit_);
260 return static_cast<uint16_t>(
261 total_bitrate_sent_.Rate(clock_->TimeInMilliseconds()).value_or(0) /
262 1000);
niklase@google.com470e71d2011-07-07 08:21:25 +0000263}
264
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000265uint32_t RTPSender::NackOverheadRate() const {
sprangcd349d92016-07-13 09:11:28 -0700266 rtc::CritScope cs(&statistics_crit_);
267 return nack_bitrate_sent_.Rate(clock_->TimeInMilliseconds()).value_or(0);
stefan@webrtc.orgd0bdab02011-10-14 14:24:54 +0000268}
269
Johannes Kron9190b822018-10-29 11:22:05 +0100270void RTPSender::SetExtmapAllowMixed(bool extmap_allow_mixed) {
271 rtc::CritScope lock(&send_critsect_);
272 rtp_header_extension_map_.SetExtmapAllowMixed(extmap_allow_mixed);
273}
274
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000275int32_t RTPSender::RegisterRtpHeaderExtension(RTPExtensionType type,
276 uint8_t id) {
tommiae695e92016-02-02 08:31:45 -0800277 rtc::CritScope lock(&send_critsect_);
Mirko Bonadei999a72a2019-07-12 17:33:46 +0000278 bool registered = rtp_header_extension_map_.RegisterByType(id, type);
279 supports_bwe_extension_ = HasBweExtension(rtp_header_extension_map_);
280 return registered ? 0 : -1;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000281}
282
Danil Chapovalov585d1aa2018-09-14 18:29:32 +0200283bool RTPSender::RegisterRtpHeaderExtension(const std::string& uri, int id) {
284 rtc::CritScope lock(&send_critsect_);
Mirko Bonadei999a72a2019-07-12 17:33:46 +0000285 bool registered = rtp_header_extension_map_.RegisterByUri(id, uri);
286 supports_bwe_extension_ = HasBweExtension(rtp_header_extension_map_);
287 return registered;
Danil Chapovalov585d1aa2018-09-14 18:29:32 +0200288}
289
stefan53b6cc32017-02-03 08:13:57 -0800290bool RTPSender::IsRtpHeaderExtensionRegistered(RTPExtensionType type) const {
tommiae695e92016-02-02 08:31:45 -0800291 rtc::CritScope lock(&send_critsect_);
guoweis@webrtc.org45362892015-03-04 22:55:15 +0000292 return rtp_header_extension_map_.IsRegistered(type);
293}
294
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000295int32_t RTPSender::DeregisterRtpHeaderExtension(RTPExtensionType type) {
tommiae695e92016-02-02 08:31:45 -0800296 rtc::CritScope lock(&send_critsect_);
Mirko Bonadei999a72a2019-07-12 17:33:46 +0000297 int32_t deregistered = rtp_header_extension_map_.Deregister(type);
298 supports_bwe_extension_ = HasBweExtension(rtp_header_extension_map_);
299 return deregistered;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000300}
301
nisse284542b2017-01-10 08:58:32 -0800302void RTPSender::SetMaxRtpPacketSize(size_t max_packet_size) {
kwibergee89e782017-08-09 17:22:01 -0700303 RTC_DCHECK_GE(max_packet_size, 100);
304 RTC_DCHECK_LE(max_packet_size, IP_PACKET_SIZE);
tommiae695e92016-02-02 08:31:45 -0800305 rtc::CritScope lock(&send_critsect_);
nisse284542b2017-01-10 08:58:32 -0800306 max_packet_size_ = max_packet_size;
niklase@google.com470e71d2011-07-07 08:21:25 +0000307}
308
nisse284542b2017-01-10 08:58:32 -0800309size_t RTPSender::MaxRtpPacketSize() const {
310 return max_packet_size_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000311}
312
pbos@webrtc.org0b0c2412015-01-13 14:15:15 +0000313void RTPSender::SetRtxStatus(int mode) {
tommiae695e92016-02-02 08:31:45 -0800314 rtc::CritScope lock(&send_critsect_);
mikhal@webrtc.orgbda7f302013-03-15 23:21:52 +0000315 rtx_ = mode;
stefan@webrtc.orgef927552014-06-05 08:25:29 +0000316}
317
pbos@webrtc.org0b0c2412015-01-13 14:15:15 +0000318int RTPSender::RtxStatus() const {
tommiae695e92016-02-02 08:31:45 -0800319 rtc::CritScope lock(&send_critsect_);
pbos@webrtc.org0b0c2412015-01-13 14:15:15 +0000320 return rtx_;
321}
322
stefan@webrtc.orgef927552014-06-05 08:25:29 +0000323void RTPSender::SetRtxSsrc(uint32_t ssrc) {
tommiae695e92016-02-02 08:31:45 -0800324 rtc::CritScope lock(&send_critsect_);
nisse7d59f6b2017-02-21 03:40:24 -0800325 ssrc_rtx_.emplace(ssrc);
pwestin@webrtc.org8281e7d2012-01-10 14:09:18 +0000326}
327
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000328uint32_t RTPSender::RtxSsrc() const {
tommiae695e92016-02-02 08:31:45 -0800329 rtc::CritScope lock(&send_critsect_);
nisse7d59f6b2017-02-21 03:40:24 -0800330 RTC_DCHECK(ssrc_rtx_);
331 return *ssrc_rtx_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000332}
333
Shao Changbine62202f2015-04-21 20:24:50 +0800334void RTPSender::SetRtxPayloadType(int payload_type,
335 int associated_payload_type) {
tommiae695e92016-02-02 08:31:45 -0800336 rtc::CritScope lock(&send_critsect_);
henrikg91d6ede2015-09-17 00:24:34 -0700337 RTC_DCHECK_LE(payload_type, 127);
338 RTC_DCHECK_LE(associated_payload_type, 127);
Shao Changbine62202f2015-04-21 20:24:50 +0800339 if (payload_type < 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100340 RTC_LOG(LS_ERROR) << "Invalid RTX payload type: " << payload_type << ".";
Shao Changbine62202f2015-04-21 20:24:50 +0800341 return;
342 }
343
344 rtx_payload_type_map_[associated_payload_type] = payload_type;
Åsa Persson6ae25722015-04-13 17:48:08 +0200345}
346
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000347void RTPSender::SetStorePacketsStatus(bool enable, uint16_t number_to_store) {
Erik Språngb9f59892019-07-19 13:52:13 +0200348 packet_history_.SetStorePacketsStatus(
349 enable ? RtpPacketHistory::StorageMode::kStoreAndCull
350 : RtpPacketHistory::StorageMode::kDisabled,
351 number_to_store);
niklase@google.com470e71d2011-07-07 08:21:25 +0000352}
353
pwestin@webrtc.orgb0061f92013-04-27 00:41:08 +0000354bool RTPSender::StorePackets() const {
Erik Språnga12b1d62018-03-14 12:39:24 +0100355 return packet_history_.GetStorageMode() !=
356 RtpPacketHistory::StorageMode::kDisabled;
pwestin@webrtc.orgb0061f92013-04-27 00:41:08 +0000357}
niklase@google.com470e71d2011-07-07 08:21:25 +0000358
Erik Språnga12b1d62018-03-14 12:39:24 +0100359int32_t RTPSender::ReSendPacket(uint16_t packet_id) {
360 // Try to find packet in RTP packet history. Also verify RTT here, so that we
361 // don't retransmit too often.
Danil Chapovalovd264df52018-06-14 12:59:38 +0200362 absl::optional<RtpPacketHistory::PacketState> stored_packet =
Danil Chapovalov6c78ff42018-10-16 11:01:05 +0200363 packet_history_.GetPacketState(packet_id);
Erik Språng0f4f0552019-05-08 10:15:05 -0700364 if (!stored_packet || stored_packet->pending_transmission) {
365 // Packet not found or already queued for retransmission, ignore.
asapersson@webrtc.org83ed0a42012-04-23 12:43:05 +0000366 return 0;
pwestin@webrtc.org8281e7d2012-01-10 14:09:18 +0000367 }
Oleh Prypin5a980492018-03-09 12:27:24 +0000368
Per Kjellander252725d2019-02-20 13:14:34 +0100369 const int32_t packet_size = static_cast<int32_t>(stored_packet->packet_size);
Erik Språngf6468d22019-07-05 16:53:43 +0200370 const bool rtx = (RtxStatus() & kRtxRetransmitted) > 0;
Erik Språng7bb37b82018-03-09 09:52:59 +0100371
Oleh Prypin5a980492018-03-09 12:27:24 +0000372 if (paced_sender_) {
Erik Språngf5815fa2019-08-21 14:27:31 +0200373 std::unique_ptr<RtpPacketToSend> packet =
374 packet_history_.GetPacketAndMarkAsPending(
375 packet_id, [&](const RtpPacketToSend& stored_packet) {
376 // Check if we're overusing retransmission bitrate.
377 // TODO(sprang): Add histograms for nack success or failure
378 // reasons.
379 std::unique_ptr<RtpPacketToSend> retransmit_packet;
380 if (retransmission_rate_limiter_ &&
381 !retransmission_rate_limiter_->TryUseRate(packet_size)) {
Erik Språngf6468d22019-07-05 16:53:43 +0200382 return retransmit_packet;
Erik Språngf5815fa2019-08-21 14:27:31 +0200383 }
384 if (rtx) {
385 retransmit_packet = BuildRtxPacket(stored_packet);
386 } else {
387 retransmit_packet =
388 absl::make_unique<RtpPacketToSend>(stored_packet);
389 }
390 if (retransmit_packet) {
391 retransmit_packet->set_retransmitted_sequence_number(
392 stored_packet.SequenceNumber());
393 }
394 return retransmit_packet;
395 });
396 if (!packet) {
397 return -1;
Erik Språng0f4f0552019-05-08 10:15:05 -0700398 }
Erik Språngf5815fa2019-08-21 14:27:31 +0200399 packet->set_packet_type(RtpPacketToSend::Type::kRetransmission);
400 paced_sender_->EnqueuePacket(std::move(packet));
Erik Språng0f4f0552019-05-08 10:15:05 -0700401
Erik Språnga12b1d62018-03-14 12:39:24 +0100402 return packet_size;
Oleh Prypin5a980492018-03-09 12:27:24 +0000403 }
Erik Språnga12b1d62018-03-14 12:39:24 +0100404
Erik Språngf6468d22019-07-05 16:53:43 +0200405 // TODO(sprang): Replace this whole code-path with a pass-through pacer.
406 // Check if we're overusing retransmission bitrate.
407 // TODO(sprang): Add histograms for nack success or failure reasons.
408 if (retransmission_rate_limiter_ &&
409 !retransmission_rate_limiter_->TryUseRate(packet_size)) {
410 return -1;
411 }
412
Erik Språnga12b1d62018-03-14 12:39:24 +0100413 std::unique_ptr<RtpPacketToSend> packet =
Danil Chapovalov6c78ff42018-10-16 11:01:05 +0200414 packet_history_.GetPacketAndSetSendTime(packet_id);
Erik Språnga12b1d62018-03-14 12:39:24 +0100415 if (!packet) {
416 // Packet could theoretically time out between the first check and this one.
417 return 0;
418 }
419
philipel8aadd502017-02-23 02:56:13 -0800420 if (!PrepareAndSendPacket(std::move(packet), rtx, true, PacedPacketInfo()))
sprang867fb522015-08-03 04:38:41 -0700421 return -1;
Erik Språnga12b1d62018-03-14 12:39:24 +0100422
Danil Chapovalov31e4e802016-08-03 18:27:40 +0200423 return packet_size;
pwestin@webrtc.org8281e7d2012-01-10 14:09:18 +0000424}
425
Steve Anton2bac7da2019-07-21 15:04:21 -0400426void RTPSender::OnReceivedAckOnSsrc(int64_t extended_highest_sequence_number) {
427 rtc::CritScope lock(&send_critsect_);
428 ssrc_has_acked_ = true;
429}
430
431void RTPSender::OnReceivedAckOnRtxSsrc(
432 int64_t extended_highest_sequence_number) {
433 rtc::CritScope lock(&send_critsect_);
434 rtx_ssrc_has_acked_ = true;
435}
436
Danil Chapovalov31e4e802016-08-03 18:27:40 +0200437bool RTPSender::SendPacketToNetwork(const RtpPacketToSend& packet,
philipel32d00102017-02-27 02:18:46 -0800438 const PacketOptions& options,
439 const PacedPacketInfo& pacing_info) {
pwestin@webrtc.orgb0061f92013-04-27 00:41:08 +0000440 int bytes_sent = -1;
phoglund@webrtc.org43da54a2013-01-25 10:53:38 +0000441 if (transport_) {
michaelt4da30442016-11-17 01:38:43 -0800442 UpdateRtpOverhead(packet);
Danil Chapovalov31e4e802016-08-03 18:27:40 +0200443 bytes_sent = transport_->SendRtp(packet.data(), packet.size(), options)
444 ? static_cast<int>(packet.size())
stefan1d8a5062015-10-02 03:39:33 -0700445 : -1;
terelius429c3452016-01-21 05:42:04 -0800446 if (event_log_ && bytes_sent > 0) {
Karl Wiberg918f50c2018-07-05 11:40:33 +0200447 event_log_->Log(absl::make_unique<RtcEventRtpPacketOutgoing>(
Elad Alon4a87e1c2017-10-03 16:11:34 +0200448 packet, pacing_info.probe_cluster_id));
terelius429c3452016-01-21 05:42:04 -0800449 }
pwestin@webrtc.org8281e7d2012-01-10 14:09:18 +0000450 }
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000451 // TODO(pwestin): Add a separate bitrate for sent bitrate after pacer.
asapersson@webrtc.org0b3c35a2012-01-16 11:06:31 +0000452 if (bytes_sent <= 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100453 RTC_LOG(LS_WARNING) << "Transport failed to send packet.";
pwestin@webrtc.orgb0061f92013-04-27 00:41:08 +0000454 return false;
pwestin@webrtc.org8281e7d2012-01-10 14:09:18 +0000455 }
pwestin@webrtc.orgb0061f92013-04-27 00:41:08 +0000456 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000457}
458
Danil Chapovalov2800d742016-08-26 18:48:46 +0200459void RTPSender::OnReceivedNack(
460 const std::vector<uint16_t>& nack_sequence_numbers,
461 int64_t avg_rtt) {
Erik Språnga12b1d62018-03-14 12:39:24 +0100462 packet_history_.SetRtt(5 + avg_rtt);
sprangcd349d92016-07-13 09:11:28 -0700463 for (uint16_t seq_no : nack_sequence_numbers) {
Erik Språnga12b1d62018-03-14 12:39:24 +0100464 const int32_t bytes_sent = ReSendPacket(seq_no);
sprangcd349d92016-07-13 09:11:28 -0700465 if (bytes_sent < 0) {
pwestin@webrtc.org8281e7d2012-01-10 14:09:18 +0000466 // Failed to send one Sequence number. Give up the rest in this nack.
Mirko Bonadei675513b2017-11-09 11:09:25 +0100467 RTC_LOG(LS_WARNING) << "Failed resending RTP packet " << seq_no
468 << ", Discard rest of packets.";
pwestin@webrtc.org8281e7d2012-01-10 14:09:18 +0000469 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000470 }
pwestin@webrtc.org8281e7d2012-01-10 14:09:18 +0000471 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000472}
473
pwestin@webrtc.orgb0061f92013-04-27 00:41:08 +0000474// Called from pacer when we can send the packet.
Erik Språngd2879622019-05-10 08:29:01 -0700475RtpPacketSendResult RTPSender::TimeToSendPacket(
476 uint32_t ssrc,
477 uint16_t sequence_number,
478 int64_t capture_time_ms,
479 bool retransmission,
480 const PacedPacketInfo& pacing_info) {
Erik Språngf5815fa2019-08-21 14:27:31 +0200481 RTC_NOTREACHED();
482 return RtpPacketSendResult::kSuccess;
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +0000483}
asapersson@webrtc.org0b3c35a2012-01-16 11:06:31 +0000484
Erik Språng9c771c22019-06-17 16:31:53 +0200485// Called from pacer when we can send the packet.
486bool RTPSender::TrySendPacket(RtpPacketToSend* packet,
487 const PacedPacketInfo& pacing_info) {
488 RTC_DCHECK(packet);
489
490 const uint32_t packet_ssrc = packet->Ssrc();
491 const auto packet_type = packet->packet_type();
492 RTC_DCHECK(packet_type.has_value());
493
494 PacketOptions options;
495 bool is_media = false;
496 bool is_rtx = false;
497 {
498 rtc::CritScope lock(&send_critsect_);
499 if (!sending_media_) {
500 return false;
501 }
502
503 switch (*packet_type) {
504 case RtpPacketToSend::Type::kAudio:
505 case RtpPacketToSend::Type::kVideo:
506 if (packet_ssrc != ssrc_) {
507 return false;
508 }
509 is_media = true;
510 break;
511 case RtpPacketToSend::Type::kRetransmission:
512 case RtpPacketToSend::Type::kPadding:
513 // Both padding and retransmission must be on either the media or the
514 // RTX stream.
515 if (packet_ssrc == ssrc_rtx_) {
516 is_rtx = true;
517 } else if (packet_ssrc != ssrc_) {
518 return false;
519 }
520 break;
521 case RtpPacketToSend::Type::kForwardErrorCorrection:
522 // FlexFEC is on separate SSRC, ULPFEC uses media SSRC.
523 if (packet_ssrc != ssrc_ && packet_ssrc != flexfec_ssrc_) {
524 return false;
525 }
526 break;
527 }
528
529 options.included_in_allocation = force_part_of_allocation_;
530 }
531
532 // Bug webrtc:7859. While FEC is invoked from rtp_sender_video, and not after
533 // the pacer, these modifications of the header below are happening after the
534 // FEC protection packets are calculated. This will corrupt recovered packets
535 // at the same place. It's not an issue for extensions, which are present in
536 // all the packets (their content just may be incorrect on recovered packets).
537 // In case of VideoTimingExtension, since it's present not in every packet,
538 // data after rtp header may be corrupted if these packets are protected by
539 // the FEC.
540 int64_t now_ms = clock_->TimeInMilliseconds();
541 int64_t diff_ms = now_ms - packet->capture_time_ms();
Erik Språng0f6191d2019-07-15 20:33:40 +0200542 if (packet->IsExtensionReserved<TransmissionOffset>()) {
543 packet->SetExtension<TransmissionOffset>(kTimestampTicksPerMs * diff_ms);
544 }
545 if (packet->IsExtensionReserved<AbsoluteSendTime>()) {
546 packet->SetExtension<AbsoluteSendTime>(
547 AbsoluteSendTime::MsTo24Bits(now_ms));
548 }
Erik Språng9c771c22019-06-17 16:31:53 +0200549
550 if (packet->HasExtension<VideoTimingExtension>()) {
551 if (populate_network2_timestamp_) {
552 packet->set_network2_time_ms(now_ms);
553 } else {
554 packet->set_pacer_exit_time_ms(now_ms);
555 }
556 }
557
558 // Downstream code actually uses this flag to distinguish between media and
559 // everything else.
560 options.is_retransmit = !is_media;
561 if (auto packet_id = packet->GetExtension<TransportSequenceNumber>()) {
562 options.packet_id = *packet_id;
563 options.included_in_feedback = true;
564 options.included_in_allocation = true;
565 AddPacketToTransportFeedback(*packet_id, *packet, pacing_info);
566 }
567
568 options.application_data.assign(packet->application_data().begin(),
569 packet->application_data().end());
570
571 if (packet->packet_type() != RtpPacketToSend::Type::kPadding &&
572 packet->packet_type() != RtpPacketToSend::Type::kRetransmission) {
573 UpdateDelayStatistics(packet->capture_time_ms(), now_ms, packet_ssrc);
574 UpdateOnSendPacket(options.packet_id, packet->capture_time_ms(),
575 packet_ssrc);
576 }
577
578 const bool send_success = SendPacketToNetwork(*packet, options, pacing_info);
579
580 // Put packet in retransmission history or update pending status even if
581 // actual sending fails.
582 if (is_media && packet->allow_retransmission()) {
583 packet_history_.PutRtpPacket(absl::make_unique<RtpPacketToSend>(*packet),
584 StorageType::kAllowRetransmission, now_ms);
585 } else if (packet->retransmitted_sequence_number()) {
586 packet_history_.MarkPacketAsSent(*packet->retransmitted_sequence_number());
587 }
588
589 if (send_success) {
590 UpdateRtpStats(*packet, is_rtx,
591 packet_type == RtpPacketToSend::Type::kRetransmission);
592
593 rtc::CritScope lock(&send_critsect_);
594 media_has_been_sent_ = true;
595 }
596
597 // Return true even if transport failed (will be handled by retransmissions
598 // instead in that case), so that PacketRouter does not have to iterate over
599 // all other RTP modules and fail to send there too.
600 return true;
601}
602
Mirko Bonadei999a72a2019-07-12 17:33:46 +0000603bool RTPSender::SupportsPadding() const {
604 rtc::CritScope lock(&send_critsect_);
605 return sending_media_ && supports_bwe_extension_;
606}
607
608bool RTPSender::SupportsRtxPayloadPadding() const {
609 rtc::CritScope lock(&send_critsect_);
610 return sending_media_ && supports_bwe_extension_ &&
611 (rtx_ & kRtxRedundantPayloads);
612}
613
Danil Chapovalov31e4e802016-08-03 18:27:40 +0200614bool RTPSender::PrepareAndSendPacket(std::unique_ptr<RtpPacketToSend> packet,
stefan@webrtc.org7c6ff2d2014-03-19 18:14:52 +0000615 bool send_over_rtx,
philipela1ed0b32016-06-01 06:31:17 -0700616 bool is_retransmit,
philipel8aadd502017-02-23 02:56:13 -0800617 const PacedPacketInfo& pacing_info) {
Danil Chapovalov31e4e802016-08-03 18:27:40 +0200618 RTC_DCHECK(packet);
619 int64_t capture_time_ms = packet->capture_time_ms();
620 RtpPacketToSend* packet_to_send = packet.get();
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +0000621
Danil Chapovalov31e4e802016-08-03 18:27:40 +0200622 std::unique_ptr<RtpPacketToSend> packet_rtx;
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +0000623 if (send_over_rtx) {
Danil Chapovalov31e4e802016-08-03 18:27:40 +0200624 packet_rtx = BuildRtxPacket(*packet);
625 if (!packet_rtx)
danilchap32cd2c42016-08-01 06:58:34 -0700626 return false;
Danil Chapovalov31e4e802016-08-03 18:27:40 +0200627 packet_to_send = packet_rtx.get();
stefan@webrtc.org9b82f5a2013-11-13 15:29:21 +0000628 }
629
ilnik10894992017-06-21 08:23:19 -0700630 // Bug webrtc:7859. While FEC is invoked from rtp_sender_video, and not after
631 // the pacer, these modifications of the header below are happening after the
632 // FEC protection packets are calculated. This will corrupt recovered packets
633 // at the same place. It's not an issue for extensions, which are present in
634 // all the packets (their content just may be incorrect on recovered packets).
635 // In case of VideoTimingExtension, since it's present not in every packet,
636 // data after rtp header may be corrupted if these packets are protected by
637 // the FEC.
solenberg@webrtc.org7ebbea12013-05-16 11:10:31 +0000638 int64_t now_ms = clock_->TimeInMilliseconds();
639 int64_t diff_ms = now_ms - capture_time_ms;
Danil Chapovalov31e4e802016-08-03 18:27:40 +0200640 packet_to_send->SetExtension<TransmissionOffset>(kTimestampTicksPerMs *
641 diff_ms);
Danil Chapovalovf3ba6482017-06-12 15:43:55 +0200642 packet_to_send->SetExtension<AbsoluteSendTime>(
643 AbsoluteSendTime::MsTo24Bits(now_ms));
sprang867fb522015-08-03 04:38:41 -0700644
Erik Språng7b52f102018-02-07 14:37:37 +0100645 if (packet_to_send->HasExtension<VideoTimingExtension>()) {
646 if (populate_network2_timestamp_) {
647 packet_to_send->set_network2_time_ms(now_ms);
648 } else {
649 packet_to_send->set_pacer_exit_time_ms(now_ms);
650 }
651 }
ilnik04f4d122017-06-19 07:18:55 -0700652
stefan1d8a5062015-10-02 03:39:33 -0700653 PacketOptions options;
Petter Strandmark26bc6692018-05-29 08:43:35 +0200654 // If we are sending over RTX, it also means this is a retransmission.
655 // E.g. RTPSender::TrySendRedundantPayloads calls PrepareAndSendPacket with
656 // send_over_rtx = true but is_retransmit = false.
657 options.is_retransmit = is_retransmit || send_over_rtx;
Sebastian Jansson30e2d6e2018-10-09 18:27:36 +0200658 bool has_transport_seq_num;
659 {
660 rtc::CritScope lock(&send_critsect_);
661 has_transport_seq_num =
662 UpdateTransportSequenceNumber(packet_to_send, &options.packet_id);
Sebastian Jansson1bca65b2018-10-10 09:58:08 +0200663 options.included_in_allocation =
664 has_transport_seq_num || force_part_of_allocation_;
665 options.included_in_feedback = has_transport_seq_num;
Sebastian Jansson30e2d6e2018-10-09 18:27:36 +0200666 }
667 if (has_transport_seq_num) {
michaelt4da30442016-11-17 01:38:43 -0800668 AddPacketToTransportFeedback(options.packet_id, *packet_to_send,
philipel8aadd502017-02-23 02:56:13 -0800669 pacing_info);
sprang867fb522015-08-03 04:38:41 -0700670 }
Dino Radaković1807d572018-02-22 14:18:06 +0100671 options.application_data.assign(packet_to_send->application_data().begin(),
672 packet_to_send->application_data().end());
sprang867fb522015-08-03 04:38:41 -0700673
asapersson35151f32016-05-02 23:44:01 -0700674 if (!is_retransmit && !send_over_rtx) {
Erik Språng9c771c22019-06-17 16:31:53 +0200675 UpdateDelayStatistics(packet->capture_time_ms(), now_ms, packet->Ssrc());
Danil Chapovalov31e4e802016-08-03 18:27:40 +0200676 UpdateOnSendPacket(options.packet_id, packet->capture_time_ms(),
677 packet->Ssrc());
stefanf116bd02015-10-27 08:29:42 -0700678 }
679
philipel32d00102017-02-27 02:18:46 -0800680 if (!SendPacketToNetwork(*packet_to_send, options, pacing_info))
Danil Chapovalov31e4e802016-08-03 18:27:40 +0200681 return false;
682
683 {
tommiae695e92016-02-02 08:31:45 -0800684 rtc::CritScope lock(&send_critsect_);
stefan@webrtc.org8b94e3d2014-07-17 16:10:14 +0000685 media_has_been_sent_ = true;
686 }
Danil Chapovalov31e4e802016-08-03 18:27:40 +0200687 UpdateRtpStats(*packet_to_send, send_over_rtx, is_retransmit);
688 return true;
sprang@webrtc.orgebad7652013-12-05 14:29:02 +0000689}
690
Danil Chapovalov31e4e802016-08-03 18:27:40 +0200691void RTPSender::UpdateRtpStats(const RtpPacketToSend& packet,
sprang@webrtc.orgebad7652013-12-05 14:29:02 +0000692 bool is_rtx,
693 bool is_retransmit) {
sprangcd349d92016-07-13 09:11:28 -0700694 int64_t now_ms = clock_->TimeInMilliseconds();
sprang@webrtc.org5314e852014-01-27 13:20:36 +0000695
danilchap7c9426c2016-04-14 03:05:31 -0700696 rtc::CritScope lock(&statistics_crit_);
Danil Chapovalovd69e5262016-09-20 15:48:09 +0200697 StreamDataCounters* counters = is_rtx ? &rtx_rtp_stats_ : &rtp_stats_;
sprang@webrtc.orgebad7652013-12-05 14:29:02 +0000698
Danil Chapovalov31e4e802016-08-03 18:27:40 +0200699 total_bitrate_sent_.Update(packet.size(), now_ms);
asapersson@webrtc.org44149392015-02-04 08:34:47 +0000700
Danil Chapovalovd69e5262016-09-20 15:48:09 +0200701 if (counters->first_packet_time_ms == -1)
702 counters->first_packet_time_ms = now_ms;
703
Erik Språngf53cfa92019-06-12 13:58:17 +0200704 if (packet.packet_type() == RtpPacketToSend::Type::kForwardErrorCorrection) {
Niels Möllerdbb988b2018-11-15 08:05:16 +0100705 counters->fec.AddPacket(packet);
Erik Språngf53cfa92019-06-12 13:58:17 +0200706 }
Danil Chapovalovd69e5262016-09-20 15:48:09 +0200707
Danil Chapovalov31e4e802016-08-03 18:27:40 +0200708 if (is_retransmit) {
Niels Möllerdbb988b2018-11-15 08:05:16 +0100709 counters->retransmitted.AddPacket(packet);
Danil Chapovalov31e4e802016-08-03 18:27:40 +0200710 nack_bitrate_sent_.Update(packet.size(), now_ms);
711 }
Niels Möllerdbb988b2018-11-15 08:05:16 +0100712 counters->transmitted.AddPacket(packet);
sprangcd349d92016-07-13 09:11:28 -0700713
Danil Chapovalovd69e5262016-09-20 15:48:09 +0200714 if (rtp_stats_callback_)
715 rtp_stats_callback_->DataCountersUpdated(*counters, packet.Ssrc());
sprang@webrtc.orgebad7652013-12-05 14:29:02 +0000716}
717
philipel8aadd502017-02-23 02:56:13 -0800718size_t RTPSender::TimeToSendPadding(size_t bytes,
719 const PacedPacketInfo& pacing_info) {
Erik Språngf5815fa2019-08-21 14:27:31 +0200720 // TODO(bugs.webrtc.org/10633): Remove when downstream test usage is gone.
721 size_t padding_bytes_sent = 0;
722 for (auto& packet : GeneratePadding(bytes)) {
723 const size_t packet_size = packet->payload_size() + packet->padding_size();
724 if (TrySendPacket(packet.get(), pacing_info)) {
725 padding_bytes_sent += packet_size;
726 }
727 }
728 return padding_bytes_sent;
stefan@webrtc.org508a84b2013-06-17 12:53:37 +0000729}
730
Erik Språngf6468d22019-07-05 16:53:43 +0200731std::vector<std::unique_ptr<RtpPacketToSend>> RTPSender::GeneratePadding(
732 size_t target_size_bytes) {
Erik Språng478cb462019-06-26 15:49:27 +0200733 // This method does not actually send packets, it just generates
734 // them and puts them in the pacer queue. Since this should incur
735 // low overhead, keep the lock for the scope of the method in order
736 // to make the code more readable.
Erik Språng478cb462019-06-26 15:49:27 +0200737
Erik Språngf6468d22019-07-05 16:53:43 +0200738 std::vector<std::unique_ptr<RtpPacketToSend>> padding_packets;
Erik Språng478cb462019-06-26 15:49:27 +0200739 size_t bytes_left = target_size_bytes;
Erik Språng0f6191d2019-07-15 20:33:40 +0200740 if (SupportsRtxPayloadPadding()) {
Mirko Bonadeia7e3bce2019-07-12 17:35:56 +0000741 while (bytes_left >= kMinPayloadPaddingBytes) {
Erik Språng478cb462019-06-26 15:49:27 +0200742 std::unique_ptr<RtpPacketToSend> packet =
743 packet_history_.GetPayloadPaddingPacket(
744 [&](const RtpPacketToSend& packet)
745 -> std::unique_ptr<RtpPacketToSend> {
Erik Språng478cb462019-06-26 15:49:27 +0200746 return BuildRtxPacket(packet);
747 });
748 if (!packet) {
749 break;
750 }
751
752 bytes_left -= std::min(bytes_left, packet->payload_size());
753 packet->set_packet_type(RtpPacketToSend::Type::kPadding);
Erik Språngf6468d22019-07-05 16:53:43 +0200754 padding_packets.push_back(std::move(packet));
Erik Språng478cb462019-06-26 15:49:27 +0200755 }
756 }
757
Erik Språng0f6191d2019-07-15 20:33:40 +0200758 rtc::CritScope lock(&send_critsect_);
759 if (!sending_media_) {
760 return {};
761 }
762
Erik Språng478cb462019-06-26 15:49:27 +0200763 size_t padding_bytes_in_packet;
764 const size_t max_payload_size = max_packet_size_ - RtpHeaderLength();
765 if (audio_configured_) {
766 // Allow smaller padding packets for audio.
767 padding_bytes_in_packet = rtc::SafeClamp<size_t>(
768 bytes_left, kMinAudioPaddingLength,
769 rtc::SafeMin(max_payload_size, kMaxPaddingLength));
770 } else {
771 // Always send full padding packets. This is accounted for by the
772 // RtpPacketSender, which will make sure we don't send too much padding even
773 // if a single packet is larger than requested.
774 // We do this to avoid frequently sending small packets on higher bitrates.
775 padding_bytes_in_packet = rtc::SafeMin(max_payload_size, kMaxPaddingLength);
776 }
777
778 while (bytes_left > 0) {
779 auto padding_packet =
780 absl::make_unique<RtpPacketToSend>(&rtp_header_extension_map_);
781 padding_packet->set_packet_type(RtpPacketToSend::Type::kPadding);
782 padding_packet->SetMarker(false);
783 padding_packet->SetTimestamp(last_rtp_timestamp_);
784 padding_packet->set_capture_time_ms(capture_time_ms_);
785 if (rtx_ == kRtxOff) {
786 if (last_payload_type_ == -1) {
787 break;
788 }
789 // Without RTX we can't send padding in the middle of frames.
790 // For audio marker bits doesn't mark the end of a frame and frames
791 // are usually a single packet, so for now we don't apply this rule
792 // for audio.
793 if (!audio_configured_ && !last_packet_marker_bit_) {
794 break;
795 }
796
797 RTC_DCHECK(ssrc_);
798 padding_packet->SetSsrc(*ssrc_);
799 padding_packet->SetPayloadType(last_payload_type_);
800 padding_packet->SetSequenceNumber(sequence_number_++);
801 } else {
802 // Without abs-send-time or transport sequence number a media packet
803 // must be sent before padding so that the timestamps used for
804 // estimation are correct.
805 if (!media_has_been_sent_ &&
806 !(rtp_header_extension_map_.IsRegistered(AbsoluteSendTime::kId) ||
807 rtp_header_extension_map_.IsRegistered(
808 TransportSequenceNumber::kId))) {
809 break;
810 }
811 // Only change the timestamp of padding packets sent over RTX.
812 // Padding only packets over RTP has to be sent as part of a media
813 // frame (and therefore the same timestamp).
814 int64_t now_ms = clock_->TimeInMilliseconds();
815 if (last_timestamp_time_ms_ > 0) {
816 padding_packet->SetTimestamp(padding_packet->Timestamp() +
817 (now_ms - last_timestamp_time_ms_) *
818 kTimestampTicksPerMs);
819 padding_packet->set_capture_time_ms(padding_packet->capture_time_ms() +
820 (now_ms - last_timestamp_time_ms_));
821 }
822 RTC_DCHECK(ssrc_rtx_);
823 padding_packet->SetSsrc(*ssrc_rtx_);
824 padding_packet->SetSequenceNumber(sequence_number_rtx_++);
825 padding_packet->SetPayloadType(rtx_payload_type_map_.begin()->second);
826 }
827
Erik Språngf6468d22019-07-05 16:53:43 +0200828 if (rtp_header_extension_map_.IsRegistered(TransportSequenceNumber::kId)) {
829 padding_packet->ReserveExtension<TransportSequenceNumber>();
830 }
Erik Språng0f6191d2019-07-15 20:33:40 +0200831 if (rtp_header_extension_map_.IsRegistered(TransmissionOffset::kId)) {
832 padding_packet->ReserveExtension<TransmissionOffset>();
833 }
834 if (rtp_header_extension_map_.IsRegistered(AbsoluteSendTime::kId)) {
835 padding_packet->ReserveExtension<AbsoluteSendTime>();
836 }
837
Erik Språng478cb462019-06-26 15:49:27 +0200838 padding_packet->SetPadding(padding_bytes_in_packet);
839 bytes_left -= std::min(bytes_left, padding_bytes_in_packet);
Erik Språngf6468d22019-07-05 16:53:43 +0200840 padding_packets.push_back(std::move(padding_packet));
Erik Språng478cb462019-06-26 15:49:27 +0200841 }
Erik Språngf6468d22019-07-05 16:53:43 +0200842
843 return padding_packets;
Erik Språng478cb462019-06-26 15:49:27 +0200844}
845
Danil Chapovalov31e4e802016-08-03 18:27:40 +0200846bool RTPSender::SendToNetwork(std::unique_ptr<RtpPacketToSend> packet,
Erik Språng13eb7642019-06-24 10:58:48 +0200847 StorageType storage) {
Danil Chapovalov31e4e802016-08-03 18:27:40 +0200848 RTC_DCHECK(packet);
solenberg@webrtc.org7ebbea12013-05-16 11:10:31 +0000849 int64_t now_ms = clock_->TimeInMilliseconds();
850
brandtr9dfff292016-11-14 05:14:50 -0800851 uint32_t ssrc = packet->Ssrc();
Peter Boströme23e7372015-10-08 11:44:14 +0200852 if (paced_sender_) {
Erik Språng13eb7642019-06-24 10:58:48 +0200853 auto packet_type = packet->packet_type();
Erik Språngf6468d22019-07-05 16:53:43 +0200854 RTC_CHECK(packet_type) << "Packet type must be set before sending.";
855
Erik Språnga57711c2019-07-24 10:47:20 +0200856 if (packet->capture_time_ms() <= 0) {
857 packet->set_capture_time_ms(now_ms);
858 }
859
Erik Språngf5815fa2019-08-21 14:27:31 +0200860 packet->set_allow_retransmission(storage ==
861 StorageType::kAllowRetransmission);
862 paced_sender_->EnqueuePacket(std::move(packet));
Danil Chapovalov31e4e802016-08-03 18:27:40 +0200863
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700864 return true;
stefan@webrtc.orgddfdfed2012-07-03 13:21:22 +0000865 }
Stefan Holmerf5dca482016-01-27 12:58:51 +0100866
867 PacketOptions options;
Petter Strandmark26bc6692018-05-29 08:43:35 +0200868 options.is_retransmit = false;
Sebastian Jansson30e2d6e2018-10-09 18:27:36 +0200869
Danil Chapovalovaf52b682018-11-27 10:48:27 +0100870 // |capture_time_ms| <= 0 is considered invalid.
871 // TODO(holmer): This should be changed all over Video Engine so that negative
872 // time is consider invalid, while 0 is considered a valid time.
873 if (packet->capture_time_ms() > 0) {
874 packet->SetExtension<TransmissionOffset>(
875 kTimestampTicksPerMs * (now_ms - packet->capture_time_ms()));
876
877 if (populate_network2_timestamp_ &&
878 packet->HasExtension<VideoTimingExtension>()) {
879 packet->set_network2_time_ms(now_ms);
880 }
881 }
882 packet->SetExtension<AbsoluteSendTime>(AbsoluteSendTime::MsTo24Bits(now_ms));
883
Sebastian Jansson30e2d6e2018-10-09 18:27:36 +0200884 bool has_transport_seq_num;
885 {
886 rtc::CritScope lock(&send_critsect_);
887 has_transport_seq_num =
888 UpdateTransportSequenceNumber(packet.get(), &options.packet_id);
Sebastian Jansson1bca65b2018-10-10 09:58:08 +0200889 options.included_in_allocation =
890 has_transport_seq_num || force_part_of_allocation_;
891 options.included_in_feedback = has_transport_seq_num;
Sebastian Jansson30e2d6e2018-10-09 18:27:36 +0200892 }
893 if (has_transport_seq_num) {
michaelt4da30442016-11-17 01:38:43 -0800894 AddPacketToTransportFeedback(options.packet_id, *packet.get(),
philipel8aadd502017-02-23 02:56:13 -0800895 PacedPacketInfo());
Stefan Holmerf5dca482016-01-27 12:58:51 +0100896 }
Dino Radaković1807d572018-02-22 14:18:06 +0100897 options.application_data.assign(packet->application_data().begin(),
898 packet->application_data().end());
Stefan Holmerf5dca482016-01-27 12:58:51 +0100899
Erik Språng9c771c22019-06-17 16:31:53 +0200900 UpdateDelayStatistics(packet->capture_time_ms(), now_ms, packet->Ssrc());
Danil Chapovalov31e4e802016-08-03 18:27:40 +0200901 UpdateOnSendPacket(options.packet_id, packet->capture_time_ms(),
902 packet->Ssrc());
903
philipel32d00102017-02-27 02:18:46 -0800904 bool sent = SendPacketToNetwork(*packet, options, PacedPacketInfo());
Danil Chapovalov31e4e802016-08-03 18:27:40 +0200905
906 if (sent) {
907 {
908 rtc::CritScope lock(&send_critsect_);
909 media_has_been_sent_ = true;
910 }
911 UpdateRtpStats(*packet, false, false);
912 }
sprang@webrtc.orgc957ffc2015-02-02 13:08:02 +0000913
brandtr9dfff292016-11-14 05:14:50 -0800914 // To support retransmissions, we store the media packet as sent in the
915 // packet history (even if send failed).
916 if (storage == kAllowRetransmission) {
Danil Chapovalov603ce982017-12-27 11:32:50 +0100917 RTC_DCHECK_EQ(ssrc, SSRC());
Erik Språnga12b1d62018-03-14 12:39:24 +0100918 packet_history_.PutRtpPacket(std::move(packet), storage, now_ms);
brandtr9dfff292016-11-14 05:14:50 -0800919 }
Peter Boströme23e7372015-10-08 11:44:14 +0200920
Danil Chapovalov31e4e802016-08-03 18:27:40 +0200921 return sent;
stefan@webrtc.org6a4bef42011-12-22 12:52:41 +0000922}
923
Johannes Kron4a8a5e72018-09-26 09:57:48 +0200924void RTPSender::RecomputeMaxSendDelay() {
925 max_delay_it_ = send_delays_.begin();
926 for (auto it = send_delays_.begin(); it != send_delays_.end(); ++it) {
927 if (it->second >= max_delay_it_->second) {
928 max_delay_it_ = it;
929 }
930 }
931}
932
Erik Språng9c771c22019-06-17 16:31:53 +0200933void RTPSender::UpdateDelayStatistics(int64_t capture_time_ms,
934 int64_t now_ms,
935 uint32_t ssrc) {
asapersson35151f32016-05-02 23:44:01 -0700936 if (!send_side_delay_observer_ || capture_time_ms <= 0)
Peter Boström71861a02015-05-28 14:45:36 +0200937 return;
938
Johannes Kron4a8a5e72018-09-26 09:57:48 +0200939 int avg_delay_ms = 0;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000940 int max_delay_ms = 0;
Henrik Boström9fe18342019-05-16 18:38:20 +0200941 uint64_t total_packet_send_delay_ms = 0;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000942 {
danilchap7c9426c2016-04-14 03:05:31 -0700943 rtc::CritScope cs(&statistics_crit_);
Johannes Kron4a8a5e72018-09-26 09:57:48 +0200944 // Compute the max and average of the recent capture-to-send delays.
945 // The time complexity of the current approach depends on the distribution
946 // of the delay values. This could be done more efficiently.
947
948 // Remove elements older than kSendSideDelayWindowMs.
949 auto lower_bound =
950 send_delays_.lower_bound(now_ms - kSendSideDelayWindowMs);
951 for (auto it = send_delays_.begin(); it != lower_bound; ++it) {
952 if (max_delay_it_ == it) {
953 max_delay_it_ = send_delays_.end();
954 }
955 sum_delays_ms_ -= it->second;
956 }
957 send_delays_.erase(send_delays_.begin(), lower_bound);
958 if (max_delay_it_ == send_delays_.end()) {
959 // Removed the previous max. Need to recompute.
960 RecomputeMaxSendDelay();
961 }
962
963 // Add the new element.
Johannes Kron965e7942018-09-13 15:36:20 +0200964 RTC_DCHECK_GE(now_ms, static_cast<int64_t>(0));
965 RTC_DCHECK_LE(now_ms, std::numeric_limits<int64_t>::max() / 2);
966 RTC_DCHECK_GE(capture_time_ms, static_cast<int64_t>(0));
967 RTC_DCHECK_LE(capture_time_ms, std::numeric_limits<int64_t>::max() / 2);
968 int64_t diff_ms = now_ms - capture_time_ms;
969 RTC_DCHECK_GE(diff_ms, static_cast<int64_t>(0));
970 RTC_DCHECK_LE(diff_ms,
971 static_cast<int64_t>(std::numeric_limits<int>::max()));
Johannes Kron4a8a5e72018-09-26 09:57:48 +0200972 int new_send_delay = rtc::dchecked_cast<int>(now_ms - capture_time_ms);
973 SendDelayMap::iterator it;
974 bool inserted;
975 std::tie(it, inserted) =
976 send_delays_.insert(std::make_pair(now_ms, new_send_delay));
977 if (!inserted) {
978 // TODO(terelius): If we have multiple delay measurements during the same
979 // millisecond then we keep the most recent one. It is not clear that this
980 // is the right decision, but it preserves an earlier behavior.
981 int previous_send_delay = it->second;
982 sum_delays_ms_ -= previous_send_delay;
983 it->second = new_send_delay;
984 if (max_delay_it_ == it && new_send_delay < previous_send_delay) {
985 RecomputeMaxSendDelay();
986 }
Peter Boström71861a02015-05-28 14:45:36 +0200987 }
Johannes Kron4a8a5e72018-09-26 09:57:48 +0200988 if (max_delay_it_ == send_delays_.end() ||
989 it->second >= max_delay_it_->second) {
990 max_delay_it_ = it;
991 }
992 sum_delays_ms_ += new_send_delay;
Henrik Boström9fe18342019-05-16 18:38:20 +0200993 total_packet_send_delay_ms_ += new_send_delay;
994 total_packet_send_delay_ms = total_packet_send_delay_ms_;
Johannes Kron4a8a5e72018-09-26 09:57:48 +0200995
996 size_t num_delays = send_delays_.size();
997 RTC_DCHECK(max_delay_it_ != send_delays_.end());
998 max_delay_ms = rtc::dchecked_cast<int>(max_delay_it_->second);
999 int64_t avg_ms = (sum_delays_ms_ + num_delays / 2) / num_delays;
1000 RTC_DCHECK_GE(avg_ms, static_cast<int64_t>(0));
1001 RTC_DCHECK_LE(avg_ms,
1002 static_cast<int64_t>(std::numeric_limits<int>::max()));
1003 avg_delay_ms =
1004 rtc::dchecked_cast<int>((sum_delays_ms_ + num_delays / 2) / num_delays);
stefan@webrtc.org168f23f2014-07-11 13:44:02 +00001005 }
Henrik Boström9fe18342019-05-16 18:38:20 +02001006 send_side_delay_observer_->SendSideDelayUpdated(
1007 avg_delay_ms, max_delay_ms, total_packet_send_delay_ms, ssrc);
stefan@webrtc.org0a3c1472013-12-05 14:05:07 +00001008}
1009
asapersson35151f32016-05-02 23:44:01 -07001010void RTPSender::UpdateOnSendPacket(int packet_id,
1011 int64_t capture_time_ms,
1012 uint32_t ssrc) {
1013 if (!send_packet_observer_ || capture_time_ms <= 0 || packet_id == -1)
1014 return;
1015
1016 send_packet_observer_->OnSendPacket(packet_id, capture_time_ms, ssrc);
1017}
1018
pwestin@webrtc.orgc66e8b32012-11-07 17:01:04 +00001019void RTPSender::ProcessBitrate() {
sprangcd349d92016-07-13 09:11:28 -07001020 if (!bitrate_callback_)
pwestin@webrtc.orgc66e8b32012-11-07 17:01:04 +00001021 return;
sprangcd349d92016-07-13 09:11:28 -07001022 int64_t now_ms = clock_->TimeInMilliseconds();
1023 uint32_t ssrc;
1024 {
1025 rtc::CritScope lock(&send_critsect_);
nisse7d59f6b2017-02-21 03:40:24 -08001026 if (!ssrc_)
1027 return;
1028 ssrc = *ssrc_;
pwestin@webrtc.orgc66e8b32012-11-07 17:01:04 +00001029 }
sprangcd349d92016-07-13 09:11:28 -07001030
1031 rtc::CritScope lock(&statistics_crit_);
1032 bitrate_callback_->Notify(total_bitrate_sent_.Rate(now_ms).value_or(0),
1033 nack_bitrate_sent_.Rate(now_ms).value_or(0), ssrc);
niklase@google.com470e71d2011-07-07 08:21:25 +00001034}
1035
isheriff6b4b5f32016-06-08 00:24:21 -07001036size_t RTPSender::RtpHeaderLength() const {
tommiae695e92016-02-02 08:31:45 -08001037 rtc::CritScope lock(&send_critsect_);
guoweis@webrtc.org45362892015-03-04 22:55:15 +00001038 size_t rtp_header_length = kRtpHeaderLength;
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001039 rtp_header_length += sizeof(uint32_t) * csrcs_.size();
Danil Chapovalov7b189922018-10-03 10:15:36 +02001040 rtp_header_length += RtpHeaderExtensionSize(kFecOrPaddingExtensionSizes,
1041 rtp_header_extension_map_);
phoglund@webrtc.org43da54a2013-01-25 10:53:38 +00001042 return rtp_header_length;
niklase@google.com470e71d2011-07-07 08:21:25 +00001043}
1044
mflodmanfcf54bd2015-04-14 21:28:08 +02001045uint16_t RTPSender::AllocateSequenceNumber(uint16_t packets_to_send) {
tommiae695e92016-02-02 08:31:45 -08001046 rtc::CritScope lock(&send_critsect_);
mflodmanfcf54bd2015-04-14 21:28:08 +02001047 uint16_t first_allocated_sequence_number = sequence_number_;
1048 sequence_number_ += packets_to_send;
1049 return first_allocated_sequence_number;
niklase@google.com470e71d2011-07-07 08:21:25 +00001050}
1051
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001052void RTPSender::GetDataCounters(StreamDataCounters* rtp_stats,
1053 StreamDataCounters* rtx_stats) const {
danilchap7c9426c2016-04-14 03:05:31 -07001054 rtc::CritScope lock(&statistics_crit_);
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001055 *rtp_stats = rtp_stats_;
1056 *rtx_stats = rtx_rtp_stats_;
niklase@google.com470e71d2011-07-07 08:21:25 +00001057}
1058
Danil Chapovalov5e57b172016-09-02 19:15:59 +02001059std::unique_ptr<RtpPacketToSend> RTPSender::AllocatePacket() const {
1060 rtc::CritScope lock(&send_critsect_);
Danil Chapovalov3b4b4f52018-10-12 12:50:43 +02001061 // TODO(danilchap): Find better motivator and value for extra capacity.
1062 // RtpPacketizer might slightly miscalulate needed size,
1063 // SRTP may benefit from extra space in the buffer and do encryption in place
1064 // saving reallocation.
1065 // While sending slightly oversized packet increase chance of dropped packet,
1066 // it is better than crash on drop packet without trying to send it.
1067 static constexpr int kExtraCapacity = 16;
1068 auto packet = absl::make_unique<RtpPacketToSend>(
1069 &rtp_header_extension_map_, max_packet_size_ + kExtraCapacity);
nisse7d59f6b2017-02-21 03:40:24 -08001070 RTC_DCHECK(ssrc_);
1071 packet->SetSsrc(*ssrc_);
Danil Chapovalov5e57b172016-09-02 19:15:59 +02001072 packet->SetCsrcs(csrcs_);
1073 // Reserve extensions, if registered, RtpSender set in SendToNetwork.
1074 packet->ReserveExtension<AbsoluteSendTime>();
1075 packet->ReserveExtension<TransmissionOffset>();
1076 packet->ReserveExtension<TransportSequenceNumber>();
Niels Möller6893f3c2019-01-31 08:56:26 +01001077
Steve Anton2bac7da2019-07-21 15:04:21 -04001078 // BUNDLE requires that the receiver "bind" the received SSRC to the values
1079 // in the MID and/or (R)RID header extensions if present. Therefore, the
1080 // sender can reduce overhead by omitting these header extensions once it
1081 // knows that the receiver has "bound" the SSRC.
1082 //
1083 // The algorithm here is fairly simple: Always attach a MID and/or RID (if
1084 // configured) to the outgoing packets until an RTCP receiver report comes
1085 // back for this SSRC. That feedback indicates the receiver must have
1086 // received a packet with the SSRC and header extension(s), so the sender
1087 // then stops attaching the MID and RID.
1088 if (!ssrc_has_acked_) {
1089 // These are no-ops if the corresponding header extension is not registered.
1090 if (!mid_.empty()) {
1091 packet->SetExtension<RtpMid>(mid_);
1092 }
1093 if (!rid_.empty()) {
1094 packet->SetExtension<RtpStreamId>(rid_);
1095 }
Amit Hilbuch77938e62018-12-21 09:23:38 -08001096 }
Danil Chapovalov5e57b172016-09-02 19:15:59 +02001097 return packet;
1098}
1099
1100bool RTPSender::AssignSequenceNumber(RtpPacketToSend* packet) {
1101 rtc::CritScope lock(&send_critsect_);
1102 if (!sending_media_)
1103 return false;
nisse7d59f6b2017-02-21 03:40:24 -08001104 RTC_DCHECK(packet->Ssrc() == ssrc_);
Danil Chapovalov5e57b172016-09-02 19:15:59 +02001105 packet->SetSequenceNumber(sequence_number_++);
1106
1107 // Remember marker bit to determine if padding can be inserted with
1108 // sequence number following |packet|.
1109 last_packet_marker_bit_ = packet->Marker();
Danil Chapovalovb3179c72018-03-22 10:13:07 +01001110 // Remember payload type to use in the padding packet if rtx is disabled.
1111 last_payload_type_ = packet->PayloadType();
Danil Chapovalov5e57b172016-09-02 19:15:59 +02001112 // Save timestamps to generate timestamp field and extensions for the padding.
1113 last_rtp_timestamp_ = packet->Timestamp();
1114 last_timestamp_time_ms_ = clock_->TimeInMilliseconds();
1115 capture_time_ms_ = packet->capture_time_ms();
1116 return true;
1117}
1118
Danil Chapovalov31e4e802016-08-03 18:27:40 +02001119bool RTPSender::UpdateTransportSequenceNumber(RtpPacketToSend* packet,
Sebastian Jansson30e2d6e2018-10-09 18:27:36 +02001120 int* packet_id) {
Danil Chapovalov31e4e802016-08-03 18:27:40 +02001121 RTC_DCHECK(packet);
1122 RTC_DCHECK(packet_id);
Danil Chapovalov31e4e802016-08-03 18:27:40 +02001123 if (!rtp_header_extension_map_.IsRegistered(TransportSequenceNumber::kId))
stefana23fc622016-07-28 07:56:38 -07001124 return false;
1125
asapersson35151f32016-05-02 23:44:01 -07001126 if (!transport_sequence_number_allocator_)
1127 return false;
1128
1129 *packet_id = transport_sequence_number_allocator_->AllocateSequenceNumber();
Danil Chapovalov31e4e802016-08-03 18:27:40 +02001130
1131 if (!packet->SetExtension<TransportSequenceNumber>(*packet_id))
1132 return false;
1133
asapersson35151f32016-05-02 23:44:01 -07001134 return true;
sprang867fb522015-08-03 04:38:41 -07001135}
1136
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001137void RTPSender::SetSendingMediaStatus(bool enabled) {
tommiae695e92016-02-02 08:31:45 -08001138 rtc::CritScope lock(&send_critsect_);
phoglund@webrtc.org43da54a2013-01-25 10:53:38 +00001139 sending_media_ = enabled;
pwestin@webrtc.orgc66e8b32012-11-07 17:01:04 +00001140}
1141
1142bool RTPSender::SendingMedia() const {
tommiae695e92016-02-02 08:31:45 -08001143 rtc::CritScope lock(&send_critsect_);
phoglund@webrtc.org43da54a2013-01-25 10:53:38 +00001144 return sending_media_;
pwestin@webrtc.orgc66e8b32012-11-07 17:01:04 +00001145}
1146
Sebastian Jansson1bca65b2018-10-10 09:58:08 +02001147void RTPSender::SetAsPartOfAllocation(bool part_of_allocation) {
1148 rtc::CritScope lock(&send_critsect_);
1149 force_part_of_allocation_ = part_of_allocation;
1150}
1151
danilchap71fead22016-08-18 02:01:49 -07001152void RTPSender::SetTimestampOffset(uint32_t timestamp) {
tommiae695e92016-02-02 08:31:45 -08001153 rtc::CritScope lock(&send_critsect_);
danilchap71fead22016-08-18 02:01:49 -07001154 timestamp_offset_ = timestamp;
pwestin@webrtc.orgc66e8b32012-11-07 17:01:04 +00001155}
1156
danilchap71fead22016-08-18 02:01:49 -07001157uint32_t RTPSender::TimestampOffset() const {
tommiae695e92016-02-02 08:31:45 -08001158 rtc::CritScope lock(&send_critsect_);
danilchap71fead22016-08-18 02:01:49 -07001159 return timestamp_offset_;
pwestin@webrtc.orgc66e8b32012-11-07 17:01:04 +00001160}
1161
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001162void RTPSender::SetSSRC(uint32_t ssrc) {
Erik Språng6cacef22019-07-24 14:15:51 +02001163 {
1164 rtc::CritScope lock(&send_critsect_);
1165 if (ssrc_ == ssrc) {
1166 return; // Since it's the same SSRC, don't reset anything.
1167 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001168
Erik Språng6cacef22019-07-24 14:15:51 +02001169 ssrc_.emplace(ssrc);
1170 if (!sequence_number_forced_) {
1171 sequence_number_ = random_.Rand(1, kMaxInitRtpSeqNumber);
1172 }
pwestin@webrtc.orgc66e8b32012-11-07 17:01:04 +00001173 }
Erik Språng6cacef22019-07-24 14:15:51 +02001174
1175 // Clear RTP packet history, since any packets there belong to the old SSRC
1176 // and they may conflict with packets from the new one.
1177 packet_history_.Clear();
niklase@google.com470e71d2011-07-07 08:21:25 +00001178}
1179
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001180uint32_t RTPSender::SSRC() const {
tommiae695e92016-02-02 08:31:45 -08001181 rtc::CritScope lock(&send_critsect_);
nisse7d59f6b2017-02-21 03:40:24 -08001182 RTC_DCHECK(ssrc_);
1183 return *ssrc_;
niklase@google.com470e71d2011-07-07 08:21:25 +00001184}
1185
Amit Hilbuch77938e62018-12-21 09:23:38 -08001186void RTPSender::SetRid(const std::string& rid) {
1187 // RID is used in simulcast scenario when multiple layers share the same mid.
1188 rtc::CritScope lock(&send_critsect_);
1189 RTC_DCHECK_LE(rid.length(), RtpStreamId::kMaxValueSizeBytes);
1190 rid_ = rid;
1191}
1192
Steve Anton296a0ce2018-03-22 15:17:27 -07001193void RTPSender::SetMid(const std::string& mid) {
1194 // This is configured via the API.
1195 rtc::CritScope lock(&send_critsect_);
Steve Anton2bac7da2019-07-21 15:04:21 -04001196 RTC_DCHECK_LE(mid.length(), RtpMid::kMaxValueSizeBytes);
Steve Anton4af95842018-04-06 11:09:46 -07001197 mid_ = mid;
Steve Anton296a0ce2018-03-22 15:17:27 -07001198}
1199
Danil Chapovalovd264df52018-06-14 12:59:38 +02001200absl::optional<uint32_t> RTPSender::FlexfecSsrc() const {
Niels Möller59ab1cf2019-02-06 22:48:11 +01001201 return flexfec_ssrc_;
brandtr9dfff292016-11-14 05:14:50 -08001202}
1203
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001204void RTPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
spranga8ae6f22017-09-04 07:23:56 -07001205 RTC_DCHECK_LE(csrcs.size(), kRtpCsrcSize);
tommiae695e92016-02-02 08:31:45 -08001206 rtc::CritScope lock(&send_critsect_);
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001207 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +00001208}
1209
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001210void RTPSender::SetSequenceNumber(uint16_t seq) {
Erik Språng6cacef22019-07-24 14:15:51 +02001211 bool updated_sequence_number = false;
1212 {
1213 rtc::CritScope lock(&send_critsect_);
1214 sequence_number_forced_ = true;
1215 if (sequence_number_ != seq) {
1216 updated_sequence_number = true;
1217 }
1218 sequence_number_ = seq;
1219 }
1220
1221 if (updated_sequence_number) {
1222 // Sequence number series has been reset to a new value, clear RTP packet
1223 // history, since any packets there may conflict with new ones.
1224 packet_history_.Clear();
1225 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001226}
1227
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001228uint16_t RTPSender::SequenceNumber() const {
tommiae695e92016-02-02 08:31:45 -08001229 rtc::CritScope lock(&send_critsect_);
phoglund@webrtc.org43da54a2013-01-25 10:53:38 +00001230 return sequence_number_;
niklase@google.com470e71d2011-07-07 08:21:25 +00001231}
1232
Danil Chapovalov271195f2019-02-11 11:30:03 +01001233static void CopyHeaderAndExtensionsToRtxPacket(const RtpPacketToSend& packet,
1234 RtpPacketToSend* rtx_packet) {
Amit Hilbuch77938e62018-12-21 09:23:38 -08001235 // Set the relevant fixed packet headers. The following are not set:
1236 // * Payload type - it is replaced in rtx packets.
1237 // * Sequence number - RTX has a separate sequence numbering.
1238 // * SSRC - RTX stream has its own SSRC.
1239 rtx_packet->SetMarker(packet.Marker());
1240 rtx_packet->SetTimestamp(packet.Timestamp());
1241
1242 // Set the variable fields in the packet header:
1243 // * CSRCs - must be set before header extensions.
1244 // * Header extensions - replace Rid header with RepairedRid header.
1245 const std::vector<uint32_t> csrcs = packet.Csrcs();
1246 rtx_packet->SetCsrcs(csrcs);
Steve Anton2bac7da2019-07-21 15:04:21 -04001247 for (int extension_num = kRtpExtensionNone + 1;
1248 extension_num < kRtpExtensionNumberOfExtensions; ++extension_num) {
1249 auto extension = static_cast<RTPExtensionType>(extension_num);
Amit Hilbuch77938e62018-12-21 09:23:38 -08001250
Steve Anton2bac7da2019-07-21 15:04:21 -04001251 // Stream ID header extensions (MID, RSID) are sent per-SSRC. Since RTX
1252 // operates on a different SSRC, the presence and values of these header
1253 // extensions should be determined separately and not blindly copied.
1254 if (extension == kRtpExtensionMid ||
1255 extension == kRtpExtensionRtpStreamId) {
Amit Hilbuch77938e62018-12-21 09:23:38 -08001256 continue;
1257 }
1258
Steve Anton2bac7da2019-07-21 15:04:21 -04001259 // Empty extensions should be supported, so not checking |source.empty()|.
1260 if (!packet.HasExtension(extension)) {
1261 continue;
1262 }
1263
1264 rtc::ArrayView<const uint8_t> source = packet.FindExtension(extension);
Amit Hilbuch77938e62018-12-21 09:23:38 -08001265
1266 rtc::ArrayView<uint8_t> destination =
Steve Anton2bac7da2019-07-21 15:04:21 -04001267 rtx_packet->AllocateExtension(extension, source.size());
Amit Hilbuch77938e62018-12-21 09:23:38 -08001268
1269 // Could happen if any:
1270 // 1. Extension has 0 length.
1271 // 2. Extension is not registered in destination.
1272 // 3. Allocating extension in destination failed.
1273 if (destination.empty() || source.size() != destination.size()) {
1274 continue;
1275 }
1276
1277 std::memcpy(destination.begin(), source.begin(), destination.size());
1278 }
Amit Hilbuch77938e62018-12-21 09:23:38 -08001279}
1280
1281std::unique_ptr<RtpPacketToSend> RTPSender::BuildRtxPacket(
1282 const RtpPacketToSend& packet) {
Danil Chapovalov271195f2019-02-11 11:30:03 +01001283 std::unique_ptr<RtpPacketToSend> rtx_packet;
Amit Hilbuch77938e62018-12-21 09:23:38 -08001284
mikhal@webrtc.orgbda7f302013-03-15 23:21:52 +00001285 // Add original RTP header.
Danil Chapovalov31e4e802016-08-03 18:27:40 +02001286 {
1287 rtc::CritScope lock(&send_critsect_);
1288 if (!sending_media_)
1289 return nullptr;
mikhal@webrtc.orgbda7f302013-03-15 23:21:52 +00001290
nisse7d59f6b2017-02-21 03:40:24 -08001291 RTC_DCHECK(ssrc_rtx_);
1292
brandtre6f98c72016-11-11 03:28:30 -08001293 // Replace payload type.
1294 auto kv = rtx_payload_type_map_.find(packet.PayloadType());
Danil Chapovalov31e4e802016-08-03 18:27:40 +02001295 if (kv == rtx_payload_type_map_.end())
brandtre6f98c72016-11-11 03:28:30 -08001296 return nullptr;
Danil Chapovalov271195f2019-02-11 11:30:03 +01001297
1298 rtx_packet = absl::make_unique<RtpPacketToSend>(&rtp_header_extension_map_,
1299 max_packet_size_);
1300
brandtre6f98c72016-11-11 03:28:30 -08001301 rtx_packet->SetPayloadType(kv->second);
mflodman@webrtc.org9f5ebb52013-04-12 14:55:46 +00001302
Danil Chapovalov31e4e802016-08-03 18:27:40 +02001303 // Replace sequence number.
1304 rtx_packet->SetSequenceNumber(sequence_number_rtx_++);
mikhal@webrtc.orgbda7f302013-03-15 23:21:52 +00001305
Danil Chapovalov31e4e802016-08-03 18:27:40 +02001306 // Replace SSRC.
nisse7d59f6b2017-02-21 03:40:24 -08001307 rtx_packet->SetSsrc(*ssrc_rtx_);
Steve Anton296a0ce2018-03-22 15:17:27 -07001308
Danil Chapovalov271195f2019-02-11 11:30:03 +01001309 CopyHeaderAndExtensionsToRtxPacket(packet, rtx_packet.get());
1310
Steve Anton2bac7da2019-07-21 15:04:21 -04001311 // RTX packets are sent on an SSRC different from the main media, so the
1312 // decision to attach MID and/or RRID header extensions is completely
1313 // separate from that of the main media SSRC.
1314 //
1315 // Note that RTX packets must used the RepairedRtpStreamId (RRID) header
1316 // extension instead of the RtpStreamId (RID) header extension even though
1317 // the payload is identical.
1318 if (!rtx_ssrc_has_acked_) {
1319 // These are no-ops if the corresponding header extension is not
1320 // registered.
1321 if (!mid_.empty()) {
1322 rtx_packet->SetExtension<RtpMid>(mid_);
1323 }
1324 if (!rid_.empty()) {
1325 rtx_packet->SetExtension<RepairedRtpStreamId>(rid_);
1326 }
Amit Hilbuch77938e62018-12-21 09:23:38 -08001327 }
Danil Chapovalov31e4e802016-08-03 18:27:40 +02001328 }
Danil Chapovalov271195f2019-02-11 11:30:03 +01001329 RTC_DCHECK(rtx_packet);
mikhal@webrtc.orgbda7f302013-03-15 23:21:52 +00001330
Danil Chapovalov31e4e802016-08-03 18:27:40 +02001331 uint8_t* rtx_payload =
1332 rtx_packet->AllocatePayload(packet.payload_size() + kRtxHeaderSize);
Danil Chapovalov271195f2019-02-11 11:30:03 +01001333 if (rtx_payload == nullptr)
1334 return nullptr;
1335
mikhal@webrtc.orgbda7f302013-03-15 23:21:52 +00001336 // Add OSN (original sequence number).
Danil Chapovalov31e4e802016-08-03 18:27:40 +02001337 ByteWriter<uint16_t>::WriteBigEndian(rtx_payload, packet.SequenceNumber());
mikhal@webrtc.orgbda7f302013-03-15 23:21:52 +00001338
1339 // Add original payload data.
danilchap96c15872016-11-21 01:35:29 -08001340 auto payload = packet.payload();
1341 memcpy(rtx_payload + kRtxHeaderSize, payload.data(), payload.size());
Danil Chapovalov31e4e802016-08-03 18:27:40 +02001342
Dino Radaković1807d572018-02-22 14:18:06 +01001343 // Add original application data.
1344 rtx_packet->set_application_data(packet.application_data());
1345
Erik Språnga57711c2019-07-24 10:47:20 +02001346 // Copy capture time so e.g. TransmissionOffset is correctly set.
1347 rtx_packet->set_capture_time_ms(packet.capture_time_ms());
1348
Danil Chapovalov31e4e802016-08-03 18:27:40 +02001349 return rtx_packet;
mikhal@webrtc.orgbda7f302013-03-15 23:21:52 +00001350}
1351
sprang@webrtc.orgebad7652013-12-05 14:29:02 +00001352void RTPSender::RegisterRtpStatisticsCallback(
1353 StreamDataCountersCallback* callback) {
danilchap7c9426c2016-04-14 03:05:31 -07001354 rtc::CritScope cs(&statistics_crit_);
sprang@webrtc.orgebad7652013-12-05 14:29:02 +00001355 rtp_stats_callback_ = callback;
1356}
1357
1358StreamDataCountersCallback* RTPSender::GetRtpStatisticsCallback() const {
danilchap7c9426c2016-04-14 03:05:31 -07001359 rtc::CritScope cs(&statistics_crit_);
sprang@webrtc.orgebad7652013-12-05 14:29:02 +00001360 return rtp_stats_callback_;
1361}
1362
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001363uint32_t RTPSender::BitrateSent() const {
sprangcd349d92016-07-13 09:11:28 -07001364 rtc::CritScope cs(&statistics_crit_);
1365 return total_bitrate_sent_.Rate(clock_->TimeInMilliseconds()).value_or(0);
sprang@webrtc.org6811b6e2013-12-13 09:46:59 +00001366}
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001367
1368void RTPSender::SetRtpState(const RtpState& rtp_state) {
tommiae695e92016-02-02 08:31:45 -08001369 rtc::CritScope lock(&send_critsect_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001370 sequence_number_ = rtp_state.sequence_number;
1371 sequence_number_forced_ = true;
danilchap71fead22016-08-18 02:01:49 -07001372 timestamp_offset_ = rtp_state.start_timestamp;
danilchape5b41412016-08-22 03:39:23 -07001373 last_rtp_timestamp_ = rtp_state.timestamp;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001374 capture_time_ms_ = rtp_state.capture_time_ms;
1375 last_timestamp_time_ms_ = rtp_state.last_timestamp_time_ms;
stefan@webrtc.org8b94e3d2014-07-17 16:10:14 +00001376 media_has_been_sent_ = rtp_state.media_has_been_sent;
Steve Anton2bac7da2019-07-21 15:04:21 -04001377 ssrc_has_acked_ = rtp_state.ssrc_has_acked;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001378}
1379
1380RtpState RTPSender::GetRtpState() const {
tommiae695e92016-02-02 08:31:45 -08001381 rtc::CritScope lock(&send_critsect_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001382
1383 RtpState state;
1384 state.sequence_number = sequence_number_;
danilchap71fead22016-08-18 02:01:49 -07001385 state.start_timestamp = timestamp_offset_;
danilchape5b41412016-08-22 03:39:23 -07001386 state.timestamp = last_rtp_timestamp_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001387 state.capture_time_ms = capture_time_ms_;
1388 state.last_timestamp_time_ms = last_timestamp_time_ms_;
stefan@webrtc.org8b94e3d2014-07-17 16:10:14 +00001389 state.media_has_been_sent = media_has_been_sent_;
Steve Anton2bac7da2019-07-21 15:04:21 -04001390 state.ssrc_has_acked = ssrc_has_acked_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001391
1392 return state;
1393}
1394
1395void RTPSender::SetRtxRtpState(const RtpState& rtp_state) {
tommiae695e92016-02-02 08:31:45 -08001396 rtc::CritScope lock(&send_critsect_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001397 sequence_number_rtx_ = rtp_state.sequence_number;
Steve Anton2bac7da2019-07-21 15:04:21 -04001398 rtx_ssrc_has_acked_ = rtp_state.ssrc_has_acked;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001399}
1400
1401RtpState RTPSender::GetRtxRtpState() const {
tommiae695e92016-02-02 08:31:45 -08001402 rtc::CritScope lock(&send_critsect_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001403
1404 RtpState state;
1405 state.sequence_number = sequence_number_rtx_;
danilchap71fead22016-08-18 02:01:49 -07001406 state.start_timestamp = timestamp_offset_;
Steve Anton2bac7da2019-07-21 15:04:21 -04001407 state.ssrc_has_acked = rtx_ssrc_has_acked_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001408
1409 return state;
1410}
1411
philipel8aadd502017-02-23 02:56:13 -08001412void RTPSender::AddPacketToTransportFeedback(
1413 uint16_t packet_id,
1414 const RtpPacketToSend& packet,
1415 const PacedPacketInfo& pacing_info) {
michaelt4da30442016-11-17 01:38:43 -08001416 if (transport_feedback_observer_) {
Erik Språng30a276b2019-04-23 12:00:11 +02001417 size_t packet_size = packet.payload_size() + packet.padding_size();
1418 if (send_side_bwe_with_overhead_) {
1419 packet_size = packet.size();
1420 }
1421
1422 RtpPacketSendInfo packet_info;
1423 packet_info.ssrc = SSRC();
1424 packet_info.transport_sequence_number = packet_id;
Erik Språng490d76c2019-05-07 09:29:15 -07001425 packet_info.has_rtp_sequence_number = true;
Erik Språng30a276b2019-04-23 12:00:11 +02001426 packet_info.rtp_sequence_number = packet.SequenceNumber();
1427 packet_info.length = packet_size;
1428 packet_info.pacing_info = pacing_info;
1429 transport_feedback_observer_->OnAddPacket(packet_info);
michaelt4da30442016-11-17 01:38:43 -08001430 }
1431}
1432
1433void RTPSender::UpdateRtpOverhead(const RtpPacketToSend& packet) {
1434 if (!overhead_observer_)
1435 return;
nisse284542b2017-01-10 08:58:32 -08001436 size_t overhead_bytes_per_packet;
michaelt4da30442016-11-17 01:38:43 -08001437 {
1438 rtc::CritScope lock(&send_critsect_);
1439 if (rtp_overhead_bytes_per_packet_ == packet.headers_size()) {
1440 return;
1441 }
1442 rtp_overhead_bytes_per_packet_ = packet.headers_size();
nisse284542b2017-01-10 08:58:32 -08001443 overhead_bytes_per_packet = rtp_overhead_bytes_per_packet_;
michaelt4da30442016-11-17 01:38:43 -08001444 }
1445 overhead_observer_->OnOverheadChanged(overhead_bytes_per_packet);
1446}
1447
sprang168794c2017-07-06 04:38:06 -07001448int64_t RTPSender::LastTimestampTimeMs() const {
1449 rtc::CritScope lock(&send_critsect_);
1450 return last_timestamp_time_ms_;
1451}
1452
Erik Språng8b101922018-01-18 11:58:05 -08001453void RTPSender::SetRtt(int64_t rtt_ms) {
1454 packet_history_.SetRtt(rtt_ms);
Erik Språng8b101922018-01-18 11:58:05 -08001455}
Erik Språng490d76c2019-05-07 09:29:15 -07001456
1457void RTPSender::OnPacketsAcknowledged(
1458 rtc::ArrayView<const uint16_t> sequence_numbers) {
1459 packet_history_.CullAcknowledgedPackets(sequence_numbers);
1460}
pwestin@webrtc.orgc66e8b32012-11-07 17:01:04 +00001461} // namespace webrtc