blob: 78cf2817b3dd20b7dce8560900e637e7c97a0b83 [file] [log] [blame]
mflodman@webrtc.org02270cd2015-02-06 13:10:191/*
2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
3 *
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
Stefan Holmer9416ef82018-07-19 08:34:3811#include "call/rtp_video_sender.h"
mflodman@webrtc.org02270cd2015-02-06 13:10:1912
philipel25d31ec2018-08-08 14:33:0113#include <algorithm>
Stefan Holmerdbdb3a02018-07-17 14:03:4614#include <memory>
15#include <string>
16#include <utility>
17
Erik Språng845c6aa2019-05-29 11:02:2418#include "absl/algorithm/container.h"
Erik Språng6cf554e2019-10-02 18:55:3919#include "absl/strings/match.h"
Erik Språng490d76c2019-05-07 16:29:1520#include "api/array_view.h"
Niels Möller5fe95102019-03-04 15:49:2521#include "api/transport/field_trial_based_config.h"
Danil Chapovalovb529b7a2019-11-27 12:59:4122#include "api/video_codecs/video_codec.h"
Stefan Holmerdbdb3a02018-07-17 14:03:4623#include "call/rtp_transport_controller_send_interface.h"
24#include "modules/pacing/packet_router.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3125#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
Tomas Gunnarssonfae05622020-06-03 06:54:3926#include "modules/rtp_rtcp/source/rtp_rtcp_impl2.h"
Stefan Holmerdbdb3a02018-07-17 14:03:4627#include "modules/rtp_rtcp/source/rtp_sender.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3128#include "modules/video_coding/include/video_codec_interface.h"
29#include "rtc_base/checks.h"
Stefan Holmerdbdb3a02018-07-17 14:03:4630#include "rtc_base/location.h"
31#include "rtc_base/logging.h"
Marina Ciocea2e696602020-05-29 10:37:0132#include "rtc_base/task_queue.h"
Markus Handellfccb0522021-06-02 11:28:1033#include "rtc_base/trace_event.h"
mflodman@webrtc.org02270cd2015-02-06 13:10:1934
35namespace webrtc {
36
Niels Möller5fe95102019-03-04 15:49:2537namespace webrtc_internal_rtp_video_sender {
38
Erik Språngf87536c2020-03-05 09:14:0439RtpStreamSender::RtpStreamSender(
Tomas Gunnarssonf25761d2020-06-03 20:55:3340 std::unique_ptr<ModuleRtpRtcpImpl2> rtp_rtcp,
Erik Språngf87536c2020-03-05 09:14:0441 std::unique_ptr<RTPSenderVideo> sender_video,
42 std::unique_ptr<VideoFecGenerator> fec_generator)
43 : rtp_rtcp(std::move(rtp_rtcp)),
44 sender_video(std::move(sender_video)),
45 fec_generator(std::move(fec_generator)) {}
Niels Möller5fe95102019-03-04 15:49:2546
47RtpStreamSender::~RtpStreamSender() = default;
48
49} // namespace webrtc_internal_rtp_video_sender
50
kjellander02b3d272016-04-20 12:05:5451namespace {
Stefan Holmerdbdb3a02018-07-17 14:03:4652static const int kMinSendSidePacketHistorySize = 600;
Stefan Holmer64be7fa2018-10-04 13:21:5553// We don't do MTU discovery, so assume that we have the standard ethernet MTU.
54static const size_t kPathMTU = 1500;
Stefan Holmerdbdb3a02018-07-17 14:03:4655
Niels Möller5fe95102019-03-04 15:49:2556using webrtc_internal_rtp_video_sender::RtpStreamSender;
57
Erik Språngcbc0cba2020-04-18 12:36:5958bool PayloadTypeSupportsSkippingFecPackets(const std::string& payload_name,
59 const WebRtcKeyValueConfig& trials) {
Erik Språngdc34a252019-10-04 13:17:2960 const VideoCodecType codecType = PayloadStringToCodecType(payload_name);
61 if (codecType == kVideoCodecVP8 || codecType == kVideoCodecVP9) {
62 return true;
63 }
64 if (codecType == kVideoCodecGeneric &&
Erik Språngcbc0cba2020-04-18 12:36:5965 absl::StartsWith(trials.Lookup("WebRTC-GenericPictureId"), "Enabled")) {
Erik Språngdc34a252019-10-04 13:17:2966 return true;
67 }
68 return false;
69}
70
71bool ShouldDisableRedAndUlpfec(bool flexfec_enabled,
Erik Språngcbc0cba2020-04-18 12:36:5972 const RtpConfig& rtp_config,
73 const WebRtcKeyValueConfig& trials) {
Erik Språngdc34a252019-10-04 13:17:2974 // Consistency of NACK and RED+ULPFEC parameters is checked in this function.
75 const bool nack_enabled = rtp_config.nack.rtp_history_ms > 0;
76
77 // Shorthands.
78 auto IsRedEnabled = [&]() { return rtp_config.ulpfec.red_payload_type >= 0; };
79 auto IsUlpfecEnabled = [&]() {
80 return rtp_config.ulpfec.ulpfec_payload_type >= 0;
81 };
82
83 bool should_disable_red_and_ulpfec = false;
84
Erik Språngcbc0cba2020-04-18 12:36:5985 if (absl::StartsWith(trials.Lookup("WebRTC-DisableUlpFecExperiment"),
86 "Enabled")) {
Erik Språngdc34a252019-10-04 13:17:2987 RTC_LOG(LS_INFO) << "Experiment to disable sending ULPFEC is enabled.";
88 should_disable_red_and_ulpfec = true;
89 }
90
91 // If enabled, FlexFEC takes priority over RED+ULPFEC.
92 if (flexfec_enabled) {
93 if (IsUlpfecEnabled()) {
94 RTC_LOG(LS_INFO)
95 << "Both FlexFEC and ULPFEC are configured. Disabling ULPFEC.";
96 }
97 should_disable_red_and_ulpfec = true;
98 }
99
100 // Payload types without picture ID cannot determine that a stream is complete
101 // without retransmitting FEC, so using ULPFEC + NACK for H.264 (for instance)
102 // is a waste of bandwidth since FEC packets still have to be transmitted.
103 // Note that this is not the case with FlexFEC.
104 if (nack_enabled && IsUlpfecEnabled() &&
Erik Språngcbc0cba2020-04-18 12:36:59105 !PayloadTypeSupportsSkippingFecPackets(rtp_config.payload_name, trials)) {
Erik Språngdc34a252019-10-04 13:17:29106 RTC_LOG(LS_WARNING)
107 << "Transmitting payload type without picture ID using "
108 "NACK+ULPFEC is a waste of bandwidth since ULPFEC packets "
109 "also have to be retransmitted. Disabling ULPFEC.";
110 should_disable_red_and_ulpfec = true;
111 }
112
113 // Verify payload types.
114 if (IsUlpfecEnabled() ^ IsRedEnabled()) {
115 RTC_LOG(LS_WARNING)
116 << "Only RED or only ULPFEC enabled, but not both. Disabling both.";
117 should_disable_red_and_ulpfec = true;
118 }
119
120 return should_disable_red_and_ulpfec;
121}
122
Erik Språngf87536c2020-03-05 09:14:04123// TODO(brandtr): Update this function when we support multistream protection.
124std::unique_ptr<VideoFecGenerator> MaybeCreateFecGenerator(
125 Clock* clock,
126 const RtpConfig& rtp,
127 const std::map<uint32_t, RtpState>& suspended_ssrcs,
Erik Språngcbc0cba2020-04-18 12:36:59128 int simulcast_index,
129 const WebRtcKeyValueConfig& trials) {
Erik Språngf87536c2020-03-05 09:14:04130 // If flexfec is configured that takes priority.
131 if (rtp.flexfec.payload_type >= 0) {
132 RTC_DCHECK_GE(rtp.flexfec.payload_type, 0);
133 RTC_DCHECK_LE(rtp.flexfec.payload_type, 127);
134 if (rtp.flexfec.ssrc == 0) {
135 RTC_LOG(LS_WARNING) << "FlexFEC is enabled, but no FlexFEC SSRC given. "
136 "Therefore disabling FlexFEC.";
137 return nullptr;
138 }
139 if (rtp.flexfec.protected_media_ssrcs.empty()) {
140 RTC_LOG(LS_WARNING)
141 << "FlexFEC is enabled, but no protected media SSRC given. "
142 "Therefore disabling FlexFEC.";
143 return nullptr;
144 }
145
146 if (rtp.flexfec.protected_media_ssrcs.size() > 1) {
147 RTC_LOG(LS_WARNING)
148 << "The supplied FlexfecConfig contained multiple protected "
149 "media streams, but our implementation currently only "
150 "supports protecting a single media stream. "
151 "To avoid confusion, disabling FlexFEC completely.";
152 return nullptr;
153 }
154
155 if (absl::c_find(rtp.flexfec.protected_media_ssrcs,
156 rtp.ssrcs[simulcast_index]) ==
157 rtp.flexfec.protected_media_ssrcs.end()) {
158 // Media SSRC not among flexfec protected SSRCs.
159 return nullptr;
160 }
161
162 const RtpState* rtp_state = nullptr;
163 auto it = suspended_ssrcs.find(rtp.flexfec.ssrc);
164 if (it != suspended_ssrcs.end()) {
165 rtp_state = &it->second;
166 }
167
168 RTC_DCHECK_EQ(1U, rtp.flexfec.protected_media_ssrcs.size());
169 return std::make_unique<FlexfecSender>(
170 rtp.flexfec.payload_type, rtp.flexfec.ssrc,
171 rtp.flexfec.protected_media_ssrcs[0], rtp.mid, rtp.extensions,
172 RTPSender::FecExtensionSizes(), rtp_state, clock);
173 } else if (rtp.ulpfec.red_payload_type >= 0 &&
174 rtp.ulpfec.ulpfec_payload_type >= 0 &&
Erik Språngcbc0cba2020-04-18 12:36:59175 !ShouldDisableRedAndUlpfec(/*flexfec_enabled=*/false, rtp,
176 trials)) {
Erik Språngf87536c2020-03-05 09:14:04177 // Flexfec not configured, but ulpfec is and is not disabled.
178 return std::make_unique<UlpfecGenerator>(
179 rtp.ulpfec.red_payload_type, rtp.ulpfec.ulpfec_payload_type, clock);
180 }
181
182 // Not a single FEC is given.
183 return nullptr;
184}
185
Niels Möller5fe95102019-03-04 15:49:25186std::vector<RtpStreamSender> CreateRtpStreamSenders(
Sebastian Jansson572c60f2019-03-04 17:30:41187 Clock* clock,
Johannes Kron9190b822018-10-29 10:22:05188 const RtpConfig& rtp_config,
Erik Språng7ea9b802019-10-16 17:03:38189 const RtpSenderObservers& observers,
Jiawei Ou55718122018-11-09 21:17:39190 int rtcp_report_interval_ms,
Stefan Holmerdbdb3a02018-07-17 14:03:46191 Transport* send_transport,
Stefan Holmerdbdb3a02018-07-17 14:03:46192 RtcpBandwidthObserver* bandwidth_callback,
193 RtpTransportControllerSendInterface* transport,
Erik Språngf87536c2020-03-05 09:14:04194 const std::map<uint32_t, RtpState>& suspended_ssrcs,
Stefan Holmerdbdb3a02018-07-17 14:03:46195 RtcEventLog* event_log,
196 RateLimiter* retransmission_rate_limiter,
Benjamin Wright192eeec2018-10-18 00:27:25197 FrameEncryptorInterface* frame_encryptor,
Marina Cioceae77912b2020-02-27 15:16:55198 const CryptoOptions& crypto_options,
Erik Språngcbc0cba2020-04-18 12:36:59199 rtc::scoped_refptr<FrameTransformerInterface> frame_transformer,
200 const WebRtcKeyValueConfig& trials) {
Amit Hilbuch0fc28432018-12-18 21:01:47201 RTC_DCHECK_GT(rtp_config.ssrcs.size(), 0);
Benjamin Wright192eeec2018-10-18 00:27:25202
Tomas Gunnarssonf25761d2020-06-03 20:55:33203 RtpRtcpInterface::Configuration configuration;
Sebastian Jansson572c60f2019-03-04 17:30:41204 configuration.clock = clock;
Stefan Holmerdbdb3a02018-07-17 14:03:46205 configuration.audio = false;
206 configuration.receiver_only = false;
207 configuration.outgoing_transport = send_transport;
Erik Språng7ea9b802019-10-16 17:03:38208 configuration.intra_frame_callback = observers.intra_frame_callback;
Elad Alon0a8562e2019-04-09 09:55:13209 configuration.rtcp_loss_notification_observer =
Erik Språng7ea9b802019-10-16 17:03:38210 observers.rtcp_loss_notification_observer;
Stefan Holmerdbdb3a02018-07-17 14:03:46211 configuration.bandwidth_callback = bandwidth_callback;
Sebastian Janssone1795f42019-07-24 09:38:03212 configuration.network_state_estimate_observer =
213 transport->network_state_estimate_observer();
Stefan Holmerdbdb3a02018-07-17 14:03:46214 configuration.transport_feedback_callback =
215 transport->transport_feedback_observer();
Erik Språng7ea9b802019-10-16 17:03:38216 configuration.rtt_stats = observers.rtcp_rtt_stats;
217 configuration.rtcp_packet_type_counter_observer =
218 observers.rtcp_type_observer;
Danil Chapovalovbd74d5c2020-03-12 08:22:44219 configuration.report_block_data_observer =
220 observers.report_block_data_observer;
Stefan Holmerdbdb3a02018-07-17 14:03:46221 configuration.paced_sender = transport->packet_sender();
Erik Språng7ea9b802019-10-16 17:03:38222 configuration.send_bitrate_observer = observers.bitrate_observer;
223 configuration.send_side_delay_observer = observers.send_delay_observer;
224 configuration.send_packet_observer = observers.send_packet_observer;
Stefan Holmerdbdb3a02018-07-17 14:03:46225 configuration.event_log = event_log;
226 configuration.retransmission_rate_limiter = retransmission_rate_limiter;
Erik Språng7ea9b802019-10-16 17:03:38227 configuration.rtp_stats_callback = observers.rtp_stats;
Benjamin Wright192eeec2018-10-18 00:27:25228 configuration.frame_encryptor = frame_encryptor;
229 configuration.require_frame_encryption =
230 crypto_options.sframe.require_frame_encryption;
Johannes Kron9190b822018-10-29 10:22:05231 configuration.extmap_allow_mixed = rtp_config.extmap_allow_mixed;
Jiawei Ou8b5d9d82018-11-16 00:44:37232 configuration.rtcp_report_interval_ms = rtcp_report_interval_ms;
Erik Språngcbc0cba2020-04-18 12:36:59233 configuration.field_trials = &trials;
Benjamin Wright192eeec2018-10-18 00:27:25234
Niels Möller5fe95102019-03-04 15:49:25235 std::vector<RtpStreamSender> rtp_streams;
Erik Språngf87536c2020-03-05 09:14:04236
Erik Språng93f51892019-08-19 10:42:58237 RTC_DCHECK(rtp_config.rtx.ssrcs.empty() ||
Henrik Boströmf45ca372020-03-24 12:30:50238 rtp_config.rtx.ssrcs.size() == rtp_config.ssrcs.size());
Erik Språng93f51892019-08-19 10:42:58239 for (size_t i = 0; i < rtp_config.ssrcs.size(); ++i) {
Erik Språngf87536c2020-03-05 09:14:04240 RTPSenderVideo::Config video_config;
Erik Språng54d5d2c2019-08-20 15:22:36241 configuration.local_media_ssrc = rtp_config.ssrcs[i];
Erik Språngf87536c2020-03-05 09:14:04242
243 std::unique_ptr<VideoFecGenerator> fec_generator =
Erik Språngcbc0cba2020-04-18 12:36:59244 MaybeCreateFecGenerator(clock, rtp_config, suspended_ssrcs, i, trials);
Erik Språngf87536c2020-03-05 09:14:04245 configuration.fec_generator = fec_generator.get();
Niels Möller5fe95102019-03-04 15:49:25246
Henrik Boströmf45ca372020-03-24 12:30:50247 configuration.rtx_send_ssrc =
248 rtp_config.GetRtxSsrcAssociatedWithMediaSsrc(rtp_config.ssrcs[i]);
249 RTC_DCHECK_EQ(configuration.rtx_send_ssrc.has_value(),
250 !rtp_config.rtx.ssrcs.empty());
Erik Språng93f51892019-08-19 10:42:58251
Erik Språng3663f942020-02-07 09:05:15252 configuration.need_rtp_packet_infos = rtp_config.lntf.enabled;
253
Niels Moller2accc7d2021-01-12 15:54:16254 std::unique_ptr<ModuleRtpRtcpImpl2> rtp_rtcp(
255 ModuleRtpRtcpImpl2::Create(configuration));
Stefan Holmerdbdb3a02018-07-17 14:03:46256 rtp_rtcp->SetSendingStatus(false);
257 rtp_rtcp->SetSendingMediaStatus(false);
258 rtp_rtcp->SetRTCPStatus(RtcpMode::kCompound);
Erik Språngdc34a252019-10-04 13:17:29259 // Set NACK.
260 rtp_rtcp->SetStorePacketsStatus(true, kMinSendSidePacketHistorySize);
Niels Möller5fe95102019-03-04 15:49:25261
Erik Språngdc34a252019-10-04 13:17:29262 video_config.clock = configuration.clock;
263 video_config.rtp_sender = rtp_rtcp->RtpSender();
Erik Språngdc34a252019-10-04 13:17:29264 video_config.frame_encryptor = frame_encryptor;
265 video_config.require_frame_encryption =
266 crypto_options.sframe.require_frame_encryption;
Erik Språngdc34a252019-10-04 13:17:29267 video_config.enable_retransmit_all_layers = false;
Erik Språngcbc0cba2020-04-18 12:36:59268 video_config.field_trials = &trials;
Erik Språngf87536c2020-03-05 09:14:04269
270 const bool using_flexfec =
271 fec_generator &&
272 fec_generator->GetFecType() == VideoFecGenerator::FecType::kFlexFec;
Erik Språngdc34a252019-10-04 13:17:29273 const bool should_disable_red_and_ulpfec =
Erik Språngcbc0cba2020-04-18 12:36:59274 ShouldDisableRedAndUlpfec(using_flexfec, rtp_config, trials);
Erik Språngf87536c2020-03-05 09:14:04275 if (!should_disable_red_and_ulpfec &&
276 rtp_config.ulpfec.red_payload_type != -1) {
Erik Språngdc34a252019-10-04 13:17:29277 video_config.red_payload_type = rtp_config.ulpfec.red_payload_type;
278 }
Erik Språng42108882020-05-05 12:51:09279 if (fec_generator) {
280 video_config.fec_type = fec_generator->GetFecType();
281 video_config.fec_overhead_bytes = fec_generator->MaxPacketOverhead();
282 }
Marina Cioceadc69fd22020-04-10 18:19:14283 video_config.frame_transformer = frame_transformer;
Marina Cioceaf1c5b952020-06-01 10:03:09284 video_config.send_transport_queue = transport->GetWorkerQueue()->Get();
Erik Språngdc34a252019-10-04 13:17:29285 auto sender_video = std::make_unique<RTPSenderVideo>(video_config);
Erik Språngf87536c2020-03-05 09:14:04286 rtp_streams.emplace_back(std::move(rtp_rtcp), std::move(sender_video),
287 std::move(fec_generator));
Stefan Holmerdbdb3a02018-07-17 14:03:46288 }
Niels Möller5fe95102019-03-04 15:49:25289 return rtp_streams;
Stefan Holmerdbdb3a02018-07-17 14:03:46290}
291
Erik Språng6cf554e2019-10-02 18:55:39292absl::optional<VideoCodecType> GetVideoCodecType(const RtpConfig& config) {
Danil Chapovalovb529b7a2019-11-27 12:59:41293 if (config.raw_payload) {
294 return absl::nullopt;
Erik Språng6cf554e2019-10-02 18:55:39295 }
Danil Chapovalovb529b7a2019-11-27 12:59:41296 return PayloadStringToCodecType(config.payload_name);
Erik Språng6cf554e2019-10-02 18:55:39297}
Erik Språng42108882020-05-05 12:51:09298bool TransportSeqNumExtensionConfigured(const RtpConfig& config) {
299 return absl::c_any_of(config.extensions, [](const RtpExtension& ext) {
Sebastian Janssonc3eb9fd2020-01-29 16:42:52300 return ext.uri == RtpExtension::kTransportSequenceNumberUri;
301 });
302}
Danil Chapovalov0be18462021-01-20 11:11:29303
304// Returns true when some coded video sequence can be decoded starting with
305// this frame without requiring any previous frames.
306// e.g. it is the same as a key frame when spatial scalability is not used.
307// When spatial scalability is used, then it is true for layer frames of
308// a key frame without inter-layer dependencies.
309bool IsFirstFrameOfACodedVideoSequence(
310 const EncodedImage& encoded_image,
311 const CodecSpecificInfo* codec_specific_info) {
312 if (encoded_image._frameType != VideoFrameType::kVideoFrameKey) {
313 return false;
314 }
315
Danil Chapovalov37dfddd2021-01-27 18:24:23316 if (codec_specific_info != nullptr) {
317 if (codec_specific_info->generic_frame_info.has_value()) {
318 // This function is used before
319 // `codec_specific_info->generic_frame_info->frame_diffs` are calculated,
320 // so need to use a more complicated way to check for presence of the
321 // dependencies.
322 return absl::c_none_of(
323 codec_specific_info->generic_frame_info->encoder_buffers,
324 [](const CodecBufferUsage& buffer) { return buffer.referenced; });
325 }
326
327 if (codec_specific_info->codecType == VideoCodecType::kVideoCodecVP8 ||
328 codec_specific_info->codecType == VideoCodecType::kVideoCodecH264 ||
329 codec_specific_info->codecType == VideoCodecType::kVideoCodecGeneric) {
330 // These codecs do not support intra picture dependencies, so a frame
331 // marked as a key frame should be a key frame.
332 return true;
333 }
Danil Chapovalov0be18462021-01-20 11:11:29334 }
335
336 // Without depenedencies described in generic format do an educated guess.
337 // It might be wrong for VP9 with spatial layer 0 skipped or higher spatial
338 // layer not depending on the spatial layer 0. This corner case is unimportant
339 // for current usage of this helper function.
340
341 // Use <= to accept both 0 (i.e. the first) and nullopt (i.e. the only).
342 return encoded_image.SpatialIndex() <= 0;
343}
344
kjellander02b3d272016-04-20 12:05:54345} // namespace
346
Stefan Holmer9416ef82018-07-19 08:34:38347RtpVideoSender::RtpVideoSender(
Sebastian Jansson572c60f2019-03-04 17:30:41348 Clock* clock,
Tommi86952822021-11-29 09:26:40349 const std::map<uint32_t, RtpState>& suspended_ssrcs,
Stefan Holmer9416ef82018-07-19 08:34:38350 const std::map<uint32_t, RtpPayloadState>& states,
351 const RtpConfig& rtp_config,
Jiawei Ou55718122018-11-09 21:17:39352 int rtcp_report_interval_ms,
Stefan Holmer9416ef82018-07-19 08:34:38353 Transport* send_transport,
354 const RtpSenderObservers& observers,
355 RtpTransportControllerSendInterface* transport,
356 RtcEventLog* event_log,
Stefan Holmer64be7fa2018-10-04 13:21:55357 RateLimiter* retransmission_limiter,
Benjamin Wright192eeec2018-10-18 00:27:25358 std::unique_ptr<FecController> fec_controller,
359 FrameEncryptorInterface* frame_encryptor,
Marina Cioceae77912b2020-02-27 15:16:55360 const CryptoOptions& crypto_options,
361 rtc::scoped_refptr<FrameTransformerInterface> frame_transformer)
Jakob Ivarsson36274f92020-10-22 11:01:07362 : send_side_bwe_with_overhead_(!absl::StartsWith(
Erik Språngcbc0cba2020-04-18 12:36:59363 field_trials_.Lookup("WebRTC-SendSideBwe-WithOverhead"),
Jakob Ivarsson36274f92020-10-22 11:01:07364 "Disabled")),
Jakob Ivarsson9a12ee52020-11-26 15:04:18365 use_frame_rate_for_overhead_(absl::StartsWith(
366 field_trials_.Lookup("WebRTC-Video-UseFrameRateForOverhead"),
367 "Enabled")),
Sebastian Janssonc3eb9fd2020-01-29 16:42:52368 has_packet_feedback_(TransportSeqNumExtensionConfigured(rtp_config)),
philipel5b231de2021-09-01 13:21:16369 simulate_generic_structure_(absl::StartsWith(
370 field_trials_.Lookup("WebRTC-GenericCodecDependencyDescriptor"),
371 "Enabled")),
Stefan Holmer64be7fa2018-10-04 13:21:55372 active_(false),
Stefan Holmer64be7fa2018-10-04 13:21:55373 fec_controller_(std::move(fec_controller)),
Elad Alon67daf712019-06-28 16:14:36374 fec_allowed_(true),
Erik Språng7ea9b802019-10-16 17:03:38375 rtp_streams_(CreateRtpStreamSenders(clock,
376 rtp_config,
377 observers,
378 rtcp_report_interval_ms,
379 send_transport,
380 transport->GetBandwidthObserver(),
381 transport,
Tommi86952822021-11-29 09:26:40382 suspended_ssrcs,
Erik Språng7ea9b802019-10-16 17:03:38383 event_log,
384 retransmission_limiter,
Erik Språng7ea9b802019-10-16 17:03:38385 frame_encryptor,
Marina Cioceae77912b2020-02-27 15:16:55386 crypto_options,
Erik Språngcbc0cba2020-04-18 12:36:59387 std::move(frame_transformer),
388 field_trials_)),
Stefan Holmerdbdb3a02018-07-17 14:03:46389 rtp_config_(rtp_config),
Erik Språng6cf554e2019-10-02 18:55:39390 codec_type_(GetVideoCodecType(rtp_config)),
Stefan Holmer64be7fa2018-10-04 13:21:55391 transport_(transport),
392 transport_overhead_bytes_per_packet_(0),
Niels Möller949f0fd2019-01-29 08:44:24393 encoder_target_rate_bps_(0),
394 frame_counts_(rtp_config.ssrcs.size()),
Oleh Prypine8964902019-03-29 15:33:01395 frame_count_observer_(observers.frame_count_observer) {
Tommi2d319df2021-12-23 21:45:50396 transport_checker_.Detach();
Elad Alon62ce0352019-05-23 14:58:53397 RTC_DCHECK_EQ(rtp_config_.ssrcs.size(), rtp_streams_.size());
Sebastian Janssonc3eb9fd2020-01-29 16:42:52398 if (send_side_bwe_with_overhead_ && has_packet_feedback_)
399 transport_->IncludeOverheadInPacedSender();
Artem Titovea240272021-07-26 10:40:21400 // SSRCs are assumed to be sorted in the same order as `rtp_modules`.
Elad Alon62ce0352019-05-23 14:58:53401 for (uint32_t ssrc : rtp_config_.ssrcs) {
Åsa Persson4bece9a2017-10-06 08:04:04402 // Restore state if it previously existed.
403 const RtpPayloadState* state = nullptr;
404 auto it = states.find(ssrc);
405 if (it != states.end()) {
406 state = &it->second;
philipel25d31ec2018-08-08 14:33:01407 shared_frame_id_ = std::max(shared_frame_id_, state->shared_frame_id);
Åsa Persson4bece9a2017-10-06 08:04:04408 }
Erik Språngcbc0cba2020-04-18 12:36:59409 params_.push_back(RtpPayloadParams(ssrc, state, field_trials_));
Åsa Persson4bece9a2017-10-06 08:04:04410 }
Stefan Holmerdbdb3a02018-07-17 14:03:46411
412 // RTP/RTCP initialization.
413
Stefan Holmerdbdb3a02018-07-17 14:03:46414 for (size_t i = 0; i < rtp_config_.extensions.size(); ++i) {
415 const std::string& extension = rtp_config_.extensions[i].uri;
416 int id = rtp_config_.extensions[i].id;
Stefan Holmerdbdb3a02018-07-17 14:03:46417 RTC_DCHECK(RtpExtension::IsSupportedForVideo(extension));
Niels Möller5fe95102019-03-04 15:49:25418 for (const RtpStreamSender& stream : rtp_streams_) {
Sebastian Janssonf39c8152019-10-14 15:32:21419 stream.rtp_rtcp->RegisterRtpHeaderExtension(extension, id);
Stefan Holmerdbdb3a02018-07-17 14:03:46420 }
421 }
422
Tommi86952822021-11-29 09:26:40423 ConfigureSsrcs(suspended_ssrcs);
Elad Alon62ce0352019-05-23 14:58:53424 ConfigureRids();
Stefan Holmerdbdb3a02018-07-17 14:03:46425
Elad Alon62ce0352019-05-23 14:58:53426 if (!rtp_config_.mid.empty()) {
Niels Möller5fe95102019-03-04 15:49:25427 for (const RtpStreamSender& stream : rtp_streams_) {
Elad Alon62ce0352019-05-23 14:58:53428 stream.rtp_rtcp->SetMid(rtp_config_.mid);
Stefan Holmerdbdb3a02018-07-17 14:03:46429 }
430 }
431
Erik Språngf87536c2020-03-05 09:14:04432 bool fec_enabled = false;
Niels Möller5fe95102019-03-04 15:49:25433 for (const RtpStreamSender& stream : rtp_streams_) {
Amit Hilbuch38e6c662019-03-09 00:17:21434 // Simulcast has one module for each layer. Set the CNAME on all modules.
Elad Alon62ce0352019-05-23 14:58:53435 stream.rtp_rtcp->SetCNAME(rtp_config_.c_name.c_str());
Elad Alon62ce0352019-05-23 14:58:53436 stream.rtp_rtcp->SetMaxRtpPacketSize(rtp_config_.max_packet_size);
437 stream.rtp_rtcp->RegisterSendPayloadFrequency(rtp_config_.payload_type,
Niels Möller5fe95102019-03-04 15:49:25438 kVideoPayloadTypeFrequency);
Erik Språngf87536c2020-03-05 09:14:04439 if (stream.fec_generator != nullptr) {
440 fec_enabled = true;
441 }
Stefan Holmerdbdb3a02018-07-17 14:03:46442 }
Stefan Holmer64be7fa2018-10-04 13:21:55443 // Currently, both ULPFEC and FlexFEC use the same FEC rate calculation logic,
444 // so enable that logic if either of those FEC schemes are enabled.
Erik Språngf87536c2020-03-05 09:14:04445 fec_controller_->SetProtectionMethod(fec_enabled, NackEnabled());
Stefan Holmer64be7fa2018-10-04 13:21:55446
447 fec_controller_->SetProtectionCallback(this);
448 // Signal congestion controller this object is ready for OnPacket* callbacks.
Sebastian Janssonf2988552019-10-29 16:18:51449 transport_->GetStreamFeedbackProvider()->RegisterStreamFeedbackObserver(
450 rtp_config_.ssrcs, this);
Erik Språngb6bbdeb2021-08-13 14:12:41451
452 // Construction happens on the worker thread (see Call::CreateVideoSendStream)
453 // but subseqeuent calls to the RTP state will happen on one of two threads:
454 // * The pacer thread for actually sending packets.
455 // * The transport thread when tearing down and quering GetRtpState().
456 // Detach thread checkers.
457 for (const RtpStreamSender& stream : rtp_streams_) {
458 stream.rtp_rtcp->OnPacketSendingThreadSwitched();
459 }
Per83d09102016-04-15 12:59:13460}
mflodman@webrtc.org02270cd2015-02-06 13:10:19461
Stefan Holmer9416ef82018-07-19 08:34:38462RtpVideoSender::~RtpVideoSender() {
Tommi2d319df2021-12-23 21:45:50463 // TODO(bugs.webrtc.org/13517): Remove once RtpVideoSender gets deleted on the
464 // transport task queue.
465 transport_checker_.Detach();
466
Erik Språng61d17732021-02-24 15:15:30467 SetActiveModulesLocked(
468 std::vector<bool>(rtp_streams_.size(), /*active=*/false));
Sebastian Janssonf2988552019-10-29 16:18:51469 transport_->GetStreamFeedbackProvider()->DeRegisterStreamFeedbackObserver(
470 this);
Stefan Holmerdbdb3a02018-07-17 14:03:46471}
472
Stefan Holmer9416ef82018-07-19 08:34:38473void RtpVideoSender::SetActive(bool active) {
Tommi2d319df2021-12-23 21:45:50474 RTC_DCHECK_RUN_ON(&transport_checker_);
Markus Handell8fe932a2020-07-06 15:41:35475 MutexLock lock(&mutex_);
Peter Boström8b79b072016-02-26 15:31:37476 if (active_ == active)
477 return;
Niels Möller5fe95102019-03-04 15:49:25478 const std::vector<bool> active_modules(rtp_streams_.size(), active);
Markus Handell2b7d9692020-05-14 13:03:40479 SetActiveModulesLocked(active_modules);
Seth Hampsoncc7125f2018-02-02 16:46:16480}
Per512ecb32016-09-23 13:52:06481
Stefan Holmer9416ef82018-07-19 08:34:38482void RtpVideoSender::SetActiveModules(const std::vector<bool> active_modules) {
Tommi2d319df2021-12-23 21:45:50483 RTC_DCHECK_RUN_ON(&transport_checker_);
Markus Handell8fe932a2020-07-06 15:41:35484 MutexLock lock(&mutex_);
Markus Handell2b7d9692020-05-14 13:03:40485 return SetActiveModulesLocked(active_modules);
486}
487
488void RtpVideoSender::SetActiveModulesLocked(
489 const std::vector<bool> active_modules) {
Tommi2d319df2021-12-23 21:45:50490 RTC_DCHECK_RUN_ON(&transport_checker_);
Niels Möller5fe95102019-03-04 15:49:25491 RTC_DCHECK_EQ(rtp_streams_.size(), active_modules.size());
Seth Hampsoncc7125f2018-02-02 16:46:16492 active_ = false;
493 for (size_t i = 0; i < active_modules.size(); ++i) {
494 if (active_modules[i]) {
495 active_ = true;
496 }
Erik Språng61d17732021-02-24 15:15:30497
Erik Språngc96aa302021-02-25 16:05:21498 RtpRtcpInterface& rtp_module = *rtp_streams_[i].rtp_rtcp;
499 const bool was_active = rtp_module.SendingMedia();
Erik Språng61d17732021-02-24 15:15:30500 const bool should_be_active = active_modules[i];
501
Seth Hampsoncc7125f2018-02-02 16:46:16502 // Sends a kRtcpByeCode when going from true to false.
Erik Språngc96aa302021-02-25 16:05:21503 rtp_module.SetSendingStatus(active_modules[i]);
Erik Språng61d17732021-02-24 15:15:30504
505 if (was_active && !should_be_active) {
506 // Disabling media, remove from packet router map to reduce size and
507 // prevent any stray packets in the pacer from asynchronously arriving
508 // to a disabled module.
Erik Språngc96aa302021-02-25 16:05:21509 transport_->packet_router()->RemoveSendRtpModule(&rtp_module);
Erik Språng61d17732021-02-24 15:15:30510 }
511
Seth Hampsoncc7125f2018-02-02 16:46:16512 // If set to false this module won't send media.
Erik Språngc96aa302021-02-25 16:05:21513 rtp_module.SetSendingMediaStatus(active_modules[i]);
Erik Språng61d17732021-02-24 15:15:30514
515 if (!was_active && should_be_active) {
516 // Turning on media, register with packet router.
Erik Språngc96aa302021-02-25 16:05:21517 transport_->packet_router()->AddSendRtpModule(&rtp_module,
518 /*remb_candidate=*/true);
Erik Språng61d17732021-02-24 15:15:30519 }
Per512ecb32016-09-23 13:52:06520 }
mflodman@webrtc.org02270cd2015-02-06 13:10:19521}
522
Stefan Holmer9416ef82018-07-19 08:34:38523bool RtpVideoSender::IsActive() {
Tommi2d319df2021-12-23 21:45:50524 RTC_DCHECK_RUN_ON(&transport_checker_);
Markus Handell8fe932a2020-07-06 15:41:35525 MutexLock lock(&mutex_);
Markus Handell2b7d9692020-05-14 13:03:40526 return IsActiveLocked();
527}
528
529bool RtpVideoSender::IsActiveLocked() {
Niels Möller5fe95102019-03-04 15:49:25530 return active_ && !rtp_streams_.empty();
mflodman@webrtc.org02270cd2015-02-06 13:10:19531}
532
Stefan Holmer9416ef82018-07-19 08:34:38533EncodedImageCallback::Result RtpVideoSender::OnEncodedImage(
Sergey Ulanov525df3f2016-08-03 00:46:41534 const EncodedImage& encoded_image,
Danil Chapovalov383f2cf2020-08-12 09:06:53535 const CodecSpecificInfo* codec_specific_info) {
Niels Möller77536a22019-01-15 07:50:01536 fec_controller_->UpdateWithEncodedData(encoded_image.size(),
Stefan Holmer64be7fa2018-10-04 13:21:55537 encoded_image._frameType);
Markus Handell8fe932a2020-07-06 15:41:35538 MutexLock lock(&mutex_);
Niels Möller5fe95102019-03-04 15:49:25539 RTC_DCHECK(!rtp_streams_.empty());
Per512ecb32016-09-23 13:52:06540 if (!active_)
Sergey Ulanov525df3f2016-08-03 00:46:41541 return Result(Result::ERROR_SEND_FAILED);
mflodman@webrtc.org50e28162015-02-23 07:45:11542
philipelbf2b6202018-08-27 12:33:18543 shared_frame_id_++;
Niels Möllerd3b8c632018-08-27 13:33:42544 size_t stream_index = 0;
545 if (codec_specific_info &&
546 (codec_specific_info->codecType == kVideoCodecVP8 ||
547 codec_specific_info->codecType == kVideoCodecH264 ||
548 codec_specific_info->codecType == kVideoCodecGeneric)) {
549 // Map spatial index to simulcast.
550 stream_index = encoded_image.SpatialIndex().value_or(0);
551 }
Niels Möller5fe95102019-03-04 15:49:25552 RTC_DCHECK_LT(stream_index, rtp_streams_.size());
Niels Möllerbb894ff2018-03-15 11:28:53553
Niels Möller5fe95102019-03-04 15:49:25554 uint32_t rtp_timestamp =
555 encoded_image.Timestamp() +
556 rtp_streams_[stream_index].rtp_rtcp->StartTimestamp();
557
558 // RTCPSender has it's own copy of the timestamp offset, added in
559 // RTCPSender::BuildSR, hence we must not add the in the offset for this call.
560 // TODO(nisse): Delete RTCPSender:timestamp_offset_, and see if we can confine
561 // knowledge of the offset to a single place.
562 if (!rtp_streams_[stream_index].rtp_rtcp->OnSendingRtpFrame(
563 encoded_image.Timestamp(), encoded_image.capture_time_ms_,
564 rtp_config_.payload_type,
Niels Möller8f7ce222019-03-21 14:43:58565 encoded_image._frameType == VideoFrameType::kVideoFrameKey)) {
Seth Hampsoncc7125f2018-02-02 16:46:16566 // The payload router could be active but this module isn't sending.
567 return Result(Result::ERROR_SEND_FAILED);
568 }
Elad Alonb64af4b2019-06-05 09:39:37569
570 absl::optional<int64_t> expected_retransmission_time_ms;
571 if (encoded_image.RetransmissionAllowed()) {
572 expected_retransmission_time_ms =
573 rtp_streams_[stream_index].rtp_rtcp->ExpectedRetransmissionTimeMs();
574 }
Niels Möller949f0fd2019-01-29 08:44:24575
Danil Chapovalov0be18462021-01-20 11:11:29576 if (IsFirstFrameOfACodedVideoSequence(encoded_image, codec_specific_info)) {
Danil Chapovalov2272f202020-02-18 11:09:43577 // If encoder adapter produce FrameDependencyStructure, pass it so that
578 // dependency descriptor rtp header extension can be used.
579 // If not supported, disable using dependency descriptor by passing nullptr.
Danil Chapovalov748550d2021-04-29 09:42:54580 RTPSenderVideo& sender_video = *rtp_streams_[stream_index].sender_video;
581 if (codec_specific_info && codec_specific_info->template_structure) {
582 sender_video.SetVideoStructure(&*codec_specific_info->template_structure);
Emil Lundmark823ba0b2021-10-18 09:27:26583 } else if (codec_specific_info &&
Danil Chapovalov748550d2021-04-29 09:42:54584 codec_specific_info->codecType == kVideoCodecVP9) {
philipel5b231de2021-09-01 13:21:16585 const CodecSpecificInfoVP9& vp9 = codec_specific_info->codecSpecific.VP9;
586
Danil Chapovalov748550d2021-04-29 09:42:54587 FrameDependencyStructure structure =
philipel5b231de2021-09-01 13:21:16588 RtpPayloadParams::MinimalisticStructure(vp9.num_spatial_layers,
589 kMaxTemporalStreams);
590 if (vp9.ss_data_available && vp9.spatial_layer_resolution_present) {
591 for (size_t i = 0; i < vp9.num_spatial_layers; ++i) {
592 structure.resolutions.emplace_back(vp9.width[i], vp9.height[i]);
593 }
594 }
595 sender_video.SetVideoStructure(&structure);
596 } else if (simulate_generic_structure_ && codec_specific_info &&
597 codec_specific_info->codecType == kVideoCodecGeneric) {
598 FrameDependencyStructure structure =
599 RtpPayloadParams::MinimalisticStructure(
600 /*num_spatial_layers=*/1,
601 /*num_temporal_layers=*/1);
Danil Chapovalov748550d2021-04-29 09:42:54602 sender_video.SetVideoStructure(&structure);
603 } else {
604 sender_video.SetVideoStructure(nullptr);
605 }
Danil Chapovalov2272f202020-02-18 11:09:43606 }
607
Marina Ciocea3a087a82020-03-03 04:39:28608 bool send_result = rtp_streams_[stream_index].sender_video->SendEncodedImage(
609 rtp_config_.payload_type, codec_type_, rtp_timestamp, encoded_image,
Danil Chapovalov51bf2002019-10-11 08:53:27610 params_[stream_index].GetRtpVideoHeader(
611 encoded_image, codec_specific_info, shared_frame_id_),
Niels Möller5fe95102019-03-04 15:49:25612 expected_retransmission_time_ms);
Niels Möller949f0fd2019-01-29 08:44:24613 if (frame_count_observer_) {
614 FrameCounts& counts = frame_counts_[stream_index];
Niels Möller8f7ce222019-03-21 14:43:58615 if (encoded_image._frameType == VideoFrameType::kVideoFrameKey) {
Niels Möller949f0fd2019-01-29 08:44:24616 ++counts.key_frames;
Niels Möller8f7ce222019-03-21 14:43:58617 } else if (encoded_image._frameType == VideoFrameType::kVideoFrameDelta) {
Niels Möller949f0fd2019-01-29 08:44:24618 ++counts.delta_frames;
619 } else {
Niels Möller8f7ce222019-03-21 14:43:58620 RTC_DCHECK(encoded_image._frameType == VideoFrameType::kEmptyFrame);
Niels Möller949f0fd2019-01-29 08:44:24621 }
622 frame_count_observer_->FrameCountUpdated(counts,
623 rtp_config_.ssrcs[stream_index]);
624 }
sergeyu7b9feee2016-11-18 00:16:14625 if (!send_result)
Sergey Ulanov525df3f2016-08-03 00:46:41626 return Result(Result::ERROR_SEND_FAILED);
627
Niels Möller5fe95102019-03-04 15:49:25628 return Result(Result::OK, rtp_timestamp);
mflodman@webrtc.orga4ef2ce2015-02-12 09:54:18629}
630
Stefan Holmer9416ef82018-07-19 08:34:38631void RtpVideoSender::OnBitrateAllocationUpdated(
Erik Språng566124a2018-04-23 10:32:22632 const VideoBitrateAllocation& bitrate) {
Tommi2d319df2021-12-23 21:45:50633 RTC_DCHECK_RUN_ON(&transport_checker_);
Markus Handell8fe932a2020-07-06 15:41:35634 MutexLock lock(&mutex_);
Markus Handell2b7d9692020-05-14 13:03:40635 if (IsActiveLocked()) {
Oleh Prypine8964902019-03-29 15:33:01636 if (rtp_streams_.size() == 1) {
sprang1a646ee2016-12-01 14:34:11637 // If spatial scalability is enabled, it is covered by a single stream.
Niels Möller5fe95102019-03-04 15:49:25638 rtp_streams_[0].rtp_rtcp->SetVideoBitrateAllocation(bitrate);
sprang1a646ee2016-12-01 14:34:11639 } else {
Stefan Holmerf7044682018-07-17 08:16:41640 std::vector<absl::optional<VideoBitrateAllocation>> layer_bitrates =
641 bitrate.GetSimulcastAllocations();
Erik Språng566124a2018-04-23 10:32:22642 // Simulcast is in use, split the VideoBitrateAllocation into one struct
643 // per rtp stream, moving over the temporal layer allocation.
Niels Möller5fe95102019-03-04 15:49:25644 for (size_t i = 0; i < rtp_streams_.size(); ++i) {
Stefan Holmerf7044682018-07-17 08:16:41645 // The next spatial layer could be used if the current one is
646 // inactive.
647 if (layer_bitrates[i]) {
Niels Möller5fe95102019-03-04 15:49:25648 rtp_streams_[i].rtp_rtcp->SetVideoBitrateAllocation(
649 *layer_bitrates[i]);
Ilya Nikolaevskiyb0588e62018-08-27 12:12:27650 } else {
651 // Signal a 0 bitrate on a simulcast stream.
Niels Möller5fe95102019-03-04 15:49:25652 rtp_streams_[i].rtp_rtcp->SetVideoBitrateAllocation(
653 VideoBitrateAllocation());
Seth Hampson46e31ba2018-01-18 18:39:54654 }
sprang1a646ee2016-12-01 14:34:11655 }
656 }
657 }
658}
Per Kjellanderaf704182020-10-16 08:30:40659void RtpVideoSender::OnVideoLayersAllocationUpdated(
660 const VideoLayersAllocation& allocation) {
661 MutexLock lock(&mutex_);
662 if (IsActiveLocked()) {
663 for (size_t i = 0; i < rtp_streams_.size(); ++i) {
664 VideoLayersAllocation stream_allocation = allocation;
665 stream_allocation.rtp_stream_index = i;
666 rtp_streams_[i].sender_video->SetVideoLayersAllocation(
667 std::move(stream_allocation));
668 }
669 }
670}
sprang1a646ee2016-12-01 14:34:11671
Stefan Holmer9416ef82018-07-19 08:34:38672bool RtpVideoSender::NackEnabled() const {
Stefan Holmerdbdb3a02018-07-17 14:03:46673 const bool nack_enabled = rtp_config_.nack.rtp_history_ms > 0;
674 return nack_enabled;
675}
676
Erik Språng482b3ef2019-01-08 15:19:11677uint32_t RtpVideoSender::GetPacketizationOverheadRate() const {
678 uint32_t packetization_overhead_bps = 0;
Niels Möller5fe95102019-03-04 15:49:25679 for (size_t i = 0; i < rtp_streams_.size(); ++i) {
680 if (rtp_streams_[i].rtp_rtcp->SendingMedia()) {
681 packetization_overhead_bps +=
682 rtp_streams_[i].sender_video->PacketizationOverheadBps();
Erik Språng482b3ef2019-01-08 15:19:11683 }
684 }
685 return packetization_overhead_bps;
686}
687
Stefan Holmer9416ef82018-07-19 08:34:38688void RtpVideoSender::DeliverRtcp(const uint8_t* packet, size_t length) {
Stefan Holmerdbdb3a02018-07-17 14:03:46689 // Runs on a network thread.
Niels Möller5fe95102019-03-04 15:49:25690 for (const RtpStreamSender& stream : rtp_streams_)
691 stream.rtp_rtcp->IncomingRtcpPacket(packet, length);
Stefan Holmerdbdb3a02018-07-17 14:03:46692}
693
Tommi86952822021-11-29 09:26:40694void RtpVideoSender::ConfigureSsrcs(
695 const std::map<uint32_t, RtpState>& suspended_ssrcs) {
Stefan Holmerdbdb3a02018-07-17 14:03:46696 // Configure regular SSRCs.
Erik Språnga9229042019-10-24 10:39:32697 RTC_CHECK(ssrc_to_rtp_module_.empty());
Elad Alon62ce0352019-05-23 14:58:53698 for (size_t i = 0; i < rtp_config_.ssrcs.size(); ++i) {
699 uint32_t ssrc = rtp_config_.ssrcs[i];
Tomas Gunnarssonf25761d2020-06-03 20:55:33700 RtpRtcpInterface* const rtp_rtcp = rtp_streams_[i].rtp_rtcp.get();
Stefan Holmerdbdb3a02018-07-17 14:03:46701
702 // Restore RTP state if previous existed.
Tommi86952822021-11-29 09:26:40703 auto it = suspended_ssrcs.find(ssrc);
704 if (it != suspended_ssrcs.end())
Stefan Holmerdbdb3a02018-07-17 14:03:46705 rtp_rtcp->SetRtpState(it->second);
Erik Språng490d76c2019-05-07 16:29:15706
Erik Språnga9229042019-10-24 10:39:32707 ssrc_to_rtp_module_[ssrc] = rtp_rtcp;
Stefan Holmerdbdb3a02018-07-17 14:03:46708 }
709
710 // Set up RTX if available.
Elad Alon62ce0352019-05-23 14:58:53711 if (rtp_config_.rtx.ssrcs.empty())
Stefan Holmerdbdb3a02018-07-17 14:03:46712 return;
713
Elad Alon62ce0352019-05-23 14:58:53714 RTC_DCHECK_EQ(rtp_config_.rtx.ssrcs.size(), rtp_config_.ssrcs.size());
715 for (size_t i = 0; i < rtp_config_.rtx.ssrcs.size(); ++i) {
716 uint32_t ssrc = rtp_config_.rtx.ssrcs[i];
Tomas Gunnarssonf25761d2020-06-03 20:55:33717 RtpRtcpInterface* const rtp_rtcp = rtp_streams_[i].rtp_rtcp.get();
Tommi86952822021-11-29 09:26:40718 auto it = suspended_ssrcs.find(ssrc);
719 if (it != suspended_ssrcs.end())
Stefan Holmerdbdb3a02018-07-17 14:03:46720 rtp_rtcp->SetRtxState(it->second);
721 }
722
723 // Configure RTX payload types.
Elad Alon62ce0352019-05-23 14:58:53724 RTC_DCHECK_GE(rtp_config_.rtx.payload_type, 0);
Niels Möller5fe95102019-03-04 15:49:25725 for (const RtpStreamSender& stream : rtp_streams_) {
Elad Alon62ce0352019-05-23 14:58:53726 stream.rtp_rtcp->SetRtxSendPayloadType(rtp_config_.rtx.payload_type,
727 rtp_config_.payload_type);
Niels Möller5fe95102019-03-04 15:49:25728 stream.rtp_rtcp->SetRtxSendStatus(kRtxRetransmitted |
729 kRtxRedundantPayloads);
Stefan Holmerdbdb3a02018-07-17 14:03:46730 }
Elad Alon62ce0352019-05-23 14:58:53731 if (rtp_config_.ulpfec.red_payload_type != -1 &&
732 rtp_config_.ulpfec.red_rtx_payload_type != -1) {
Niels Möller5fe95102019-03-04 15:49:25733 for (const RtpStreamSender& stream : rtp_streams_) {
734 stream.rtp_rtcp->SetRtxSendPayloadType(
Elad Alon62ce0352019-05-23 14:58:53735 rtp_config_.ulpfec.red_rtx_payload_type,
736 rtp_config_.ulpfec.red_payload_type);
Stefan Holmerdbdb3a02018-07-17 14:03:46737 }
738 }
739}
740
Elad Alon62ce0352019-05-23 14:58:53741void RtpVideoSender::ConfigureRids() {
Florent Castelli463d44a2019-07-12 13:35:53742 if (rtp_config_.rids.empty())
743 return;
744
745 // Some streams could have been disabled, but the rids are still there.
746 // This will occur when simulcast has been disabled for a codec (e.g. VP9)
747 RTC_DCHECK(rtp_config_.rids.size() >= rtp_streams_.size());
748 for (size_t i = 0; i < rtp_streams_.size(); ++i) {
749 rtp_streams_[i].rtp_rtcp->SetRid(rtp_config_.rids[i]);
Amit Hilbuch77938e62018-12-21 17:23:38750 }
751}
752
Stefan Holmer9416ef82018-07-19 08:34:38753void RtpVideoSender::OnNetworkAvailability(bool network_available) {
Niels Möller5fe95102019-03-04 15:49:25754 for (const RtpStreamSender& stream : rtp_streams_) {
755 stream.rtp_rtcp->SetRTCPStatus(network_available ? rtp_config_.rtcp_mode
756 : RtcpMode::kOff);
Stefan Holmerdbdb3a02018-07-17 14:03:46757 }
758}
759
Stefan Holmer9416ef82018-07-19 08:34:38760std::map<uint32_t, RtpState> RtpVideoSender::GetRtpStates() const {
Stefan Holmerdbdb3a02018-07-17 14:03:46761 std::map<uint32_t, RtpState> rtp_states;
762
763 for (size_t i = 0; i < rtp_config_.ssrcs.size(); ++i) {
764 uint32_t ssrc = rtp_config_.ssrcs[i];
Niels Möller5fe95102019-03-04 15:49:25765 RTC_DCHECK_EQ(ssrc, rtp_streams_[i].rtp_rtcp->SSRC());
766 rtp_states[ssrc] = rtp_streams_[i].rtp_rtcp->GetRtpState();
Erik Språngf87536c2020-03-05 09:14:04767
Erik Språng42108882020-05-05 12:51:09768 // Only happens during shutdown, when RTP module is already inactive,
769 // so OK to call fec generator here.
770 if (rtp_streams_[i].fec_generator) {
771 absl::optional<RtpState> fec_state =
772 rtp_streams_[i].fec_generator->GetRtpState();
773 if (fec_state) {
774 uint32_t ssrc = rtp_config_.flexfec.ssrc;
775 rtp_states[ssrc] = *fec_state;
776 }
Erik Språngf87536c2020-03-05 09:14:04777 }
Stefan Holmerdbdb3a02018-07-17 14:03:46778 }
779
780 for (size_t i = 0; i < rtp_config_.rtx.ssrcs.size(); ++i) {
781 uint32_t ssrc = rtp_config_.rtx.ssrcs[i];
Niels Möller5fe95102019-03-04 15:49:25782 rtp_states[ssrc] = rtp_streams_[i].rtp_rtcp->GetRtxState();
Stefan Holmerdbdb3a02018-07-17 14:03:46783 }
784
Stefan Holmerdbdb3a02018-07-17 14:03:46785 return rtp_states;
786}
787
Stefan Holmer9416ef82018-07-19 08:34:38788std::map<uint32_t, RtpPayloadState> RtpVideoSender::GetRtpPayloadStates()
789 const {
Markus Handell8fe932a2020-07-06 15:41:35790 MutexLock lock(&mutex_);
Stefan Holmerdbdb3a02018-07-17 14:03:46791 std::map<uint32_t, RtpPayloadState> payload_states;
792 for (const auto& param : params_) {
793 payload_states[param.ssrc()] = param.state();
philipel25d31ec2018-08-08 14:33:01794 payload_states[param.ssrc()].shared_frame_id = shared_frame_id_;
Stefan Holmerdbdb3a02018-07-17 14:03:46795 }
796 return payload_states;
797}
Stefan Holmer64be7fa2018-10-04 13:21:55798
799void RtpVideoSender::OnTransportOverheadChanged(
800 size_t transport_overhead_bytes_per_packet) {
Markus Handell8fe932a2020-07-06 15:41:35801 MutexLock lock(&mutex_);
Stefan Holmer64be7fa2018-10-04 13:21:55802 transport_overhead_bytes_per_packet_ = transport_overhead_bytes_per_packet;
803
804 size_t max_rtp_packet_size =
805 std::min(rtp_config_.max_packet_size,
806 kPathMTU - transport_overhead_bytes_per_packet_);
Niels Möller5fe95102019-03-04 15:49:25807 for (const RtpStreamSender& stream : rtp_streams_) {
808 stream.rtp_rtcp->SetMaxRtpPacketSize(max_rtp_packet_size);
Stefan Holmer64be7fa2018-10-04 13:21:55809 }
810}
811
Sebastian Jansson82ed2e82019-10-15 13:58:37812void RtpVideoSender::OnBitrateUpdated(BitrateAllocationUpdate update,
Stefan Holmer64be7fa2018-10-04 13:21:55813 int framerate) {
814 // Substract overhead from bitrate.
Markus Handell8fe932a2020-07-06 15:41:35815 MutexLock lock(&mutex_);
Erik Språng04e1bab2020-05-07 16:18:32816 size_t num_active_streams = 0;
817 size_t overhead_bytes_per_packet = 0;
818 for (const auto& stream : rtp_streams_) {
819 if (stream.rtp_rtcp->SendingMedia()) {
820 overhead_bytes_per_packet += stream.rtp_rtcp->ExpectedPerPacketOverhead();
821 ++num_active_streams;
822 }
823 }
824 if (num_active_streams > 1) {
825 overhead_bytes_per_packet /= num_active_streams;
826 }
827
Danil Chapovalovcad3e0e2020-02-17 17:46:07828 DataSize packet_overhead = DataSize::Bytes(
Erik Språng04e1bab2020-05-07 16:18:32829 overhead_bytes_per_packet + transport_overhead_bytes_per_packet_);
Danil Chapovalovcad3e0e2020-02-17 17:46:07830 DataSize max_total_packet_size = DataSize::Bytes(
Sebastian Janssoncf41eb12019-06-10 09:30:59831 rtp_config_.max_packet_size + transport_overhead_bytes_per_packet_);
Sebastian Jansson82ed2e82019-10-15 13:58:37832 uint32_t payload_bitrate_bps = update.target_bitrate.bps();
Sebastian Janssonc3eb9fd2020-01-29 16:42:52833 if (send_side_bwe_with_overhead_ && has_packet_feedback_) {
Jakob Ivarsson9a12ee52020-11-26 15:04:18834 DataRate overhead_rate =
835 CalculateOverheadRate(update.target_bitrate, max_total_packet_size,
836 packet_overhead, Frequency::Hertz(framerate));
Sebastian Janssoncf41eb12019-06-10 09:30:59837 // TODO(srte): We probably should not accept 0 payload bitrate here.
Sebastian Jansson82ed2e82019-10-15 13:58:37838 payload_bitrate_bps = rtc::saturated_cast<uint32_t>(payload_bitrate_bps -
839 overhead_rate.bps());
Stefan Holmer64be7fa2018-10-04 13:21:55840 }
841
842 // Get the encoder target rate. It is the estimated network rate -
843 // protection overhead.
Sebastian Jansson82ed2e82019-10-15 13:58:37844 // TODO(srte): We should multiply with 255 here.
Stefan Holmer64be7fa2018-10-04 13:21:55845 encoder_target_rate_bps_ = fec_controller_->UpdateFecRates(
Sebastian Jansson82ed2e82019-10-15 13:58:37846 payload_bitrate_bps, framerate,
847 rtc::saturated_cast<uint8_t>(update.packet_loss_ratio * 256),
848 loss_mask_vector_, update.round_trip_time.ms());
Elad Alon67daf712019-06-28 16:14:36849 if (!fec_allowed_) {
850 encoder_target_rate_bps_ = payload_bitrate_bps;
851 // fec_controller_->UpdateFecRates() was still called so as to allow
Artem Titovea240272021-07-26 10:40:21852 // `fec_controller_` to update whatever internal state it might have,
853 // since `fec_allowed_` may be toggled back on at any moment.
Elad Alon67daf712019-06-28 16:14:36854 }
Erik Språng482b3ef2019-01-08 15:19:11855
Artem Titovea240272021-07-26 10:40:21856 // Subtract packetization overhead from the encoder target. If target rate
857 // is really low, cap the overhead at 50%. This also avoids the case where
858 // `encoder_target_rate_bps_` is 0 due to encoder pause event while the
859 // packetization rate is positive since packets are still flowing.
Erik Språng3c65a2b2020-10-04 09:51:22860 uint32_t packetization_rate_bps =
861 std::min(GetPacketizationOverheadRate(), encoder_target_rate_bps_ / 2);
862 encoder_target_rate_bps_ -= packetization_rate_bps;
Erik Språng482b3ef2019-01-08 15:19:11863
Stefan Holmer64be7fa2018-10-04 13:21:55864 loss_mask_vector_.clear();
865
Sebastian Janssoncf41eb12019-06-10 09:30:59866 uint32_t encoder_overhead_rate_bps = 0;
Sebastian Janssonc3eb9fd2020-01-29 16:42:52867 if (send_side_bwe_with_overhead_ && has_packet_feedback_) {
Sebastian Janssoncf41eb12019-06-10 09:30:59868 // TODO(srte): The packet size should probably be the same as in the
869 // CalculateOverheadRate call above (just max_total_packet_size), it doesn't
870 // make sense to use different packet rates for different overhead
871 // calculations.
872 DataRate encoder_overhead_rate = CalculateOverheadRate(
Danil Chapovalovcad3e0e2020-02-17 17:46:07873 DataRate::BitsPerSec(encoder_target_rate_bps_),
Erik Språng04e1bab2020-05-07 16:18:32874 max_total_packet_size - DataSize::Bytes(overhead_bytes_per_packet),
Jakob Ivarsson9a12ee52020-11-26 15:04:18875 packet_overhead, Frequency::Hertz(framerate));
Sebastian Jansson82ed2e82019-10-15 13:58:37876 encoder_overhead_rate_bps = std::min(
877 encoder_overhead_rate.bps<uint32_t>(),
878 update.target_bitrate.bps<uint32_t>() - encoder_target_rate_bps_);
Sebastian Janssoncf41eb12019-06-10 09:30:59879 }
Stefan Holmer64be7fa2018-10-04 13:21:55880 // When the field trial "WebRTC-SendSideBwe-WithOverhead" is enabled
881 // protection_bitrate includes overhead.
Erik Språngd15687d2019-01-18 09:47:07882 const uint32_t media_rate = encoder_target_rate_bps_ +
883 encoder_overhead_rate_bps +
884 packetization_rate_bps;
Danil Chapovalovcad3e0e2020-02-17 17:46:07885 RTC_DCHECK_GE(update.target_bitrate, DataRate::BitsPerSec(media_rate));
Sebastian Jansson82ed2e82019-10-15 13:58:37886 protection_bitrate_bps_ = update.target_bitrate.bps() - media_rate;
Stefan Holmer64be7fa2018-10-04 13:21:55887}
888
889uint32_t RtpVideoSender::GetPayloadBitrateBps() const {
890 return encoder_target_rate_bps_;
891}
892
893uint32_t RtpVideoSender::GetProtectionBitrateBps() const {
894 return protection_bitrate_bps_;
895}
896
Elad Alon898395d2019-04-10 13:55:00897std::vector<RtpSequenceNumberMap::Info> RtpVideoSender::GetSentRtpPacketInfos(
Elad Alon8b60e8b2019-04-08 12:14:05898 uint32_t ssrc,
Elad Alon898395d2019-04-10 13:55:00899 rtc::ArrayView<const uint16_t> sequence_numbers) const {
Elad Alon8b60e8b2019-04-08 12:14:05900 for (const auto& rtp_stream : rtp_streams_) {
901 if (ssrc == rtp_stream.rtp_rtcp->SSRC()) {
Erik Språng3663f942020-02-07 09:05:15902 return rtp_stream.rtp_rtcp->GetSentRtpPacketInfos(sequence_numbers);
Elad Alon8b60e8b2019-04-08 12:14:05903 }
904 }
Elad Alon898395d2019-04-10 13:55:00905 return std::vector<RtpSequenceNumberMap::Info>();
Elad Alon8b60e8b2019-04-08 12:14:05906}
907
Stefan Holmer64be7fa2018-10-04 13:21:55908int RtpVideoSender::ProtectionRequest(const FecProtectionParams* delta_params,
909 const FecProtectionParams* key_params,
910 uint32_t* sent_video_rate_bps,
911 uint32_t* sent_nack_rate_bps,
912 uint32_t* sent_fec_rate_bps) {
913 *sent_video_rate_bps = 0;
914 *sent_nack_rate_bps = 0;
915 *sent_fec_rate_bps = 0;
Niels Möller5fe95102019-03-04 15:49:25916 for (const RtpStreamSender& stream : rtp_streams_) {
Erik Språng1d50cb62020-07-02 15:41:32917 stream.rtp_rtcp->SetFecProtectionParams(*delta_params, *key_params);
918
919 auto send_bitrate = stream.rtp_rtcp->GetSendRates();
920 *sent_video_rate_bps += send_bitrate[RtpPacketMediaType::kVideo].bps();
921 *sent_fec_rate_bps +=
922 send_bitrate[RtpPacketMediaType::kForwardErrorCorrection].bps();
923 *sent_nack_rate_bps +=
924 send_bitrate[RtpPacketMediaType::kRetransmission].bps();
Stefan Holmer64be7fa2018-10-04 13:21:55925 }
926 return 0;
927}
928
Elad Alon8f01c4e2019-06-28 13:19:43929void RtpVideoSender::SetFecAllowed(bool fec_allowed) {
Markus Handell8fe932a2020-07-06 15:41:35930 MutexLock lock(&mutex_);
Elad Alon67daf712019-06-28 16:14:36931 fec_allowed_ = fec_allowed;
Elad Alon8f01c4e2019-06-28 13:19:43932}
933
Stefan Holmer64be7fa2018-10-04 13:21:55934void RtpVideoSender::OnPacketFeedbackVector(
Sebastian Janssonf2988552019-10-29 16:18:51935 std::vector<StreamPacketInfo> packet_feedback_vector) {
Erik Språng490d76c2019-05-07 16:29:15936 if (fec_controller_->UseLossVectorMask()) {
Markus Handell8fe932a2020-07-06 15:41:35937 MutexLock lock(&mutex_);
Sebastian Janssonf2988552019-10-29 16:18:51938 for (const StreamPacketInfo& packet : packet_feedback_vector) {
939 loss_mask_vector_.push_back(!packet.received);
Stefan Holmer64be7fa2018-10-04 13:21:55940 }
941 }
Erik Språng490d76c2019-05-07 16:29:15942
943 // Map from SSRC to all acked packets for that RTP module.
944 std::map<uint32_t, std::vector<uint16_t>> acked_packets_per_ssrc;
Sebastian Janssonf2988552019-10-29 16:18:51945 for (const StreamPacketInfo& packet : packet_feedback_vector) {
Erik Språng6a0a5592021-06-15 17:04:24946 if (packet.received && packet.ssrc) {
947 acked_packets_per_ssrc[*packet.ssrc].push_back(
948 packet.rtp_sequence_number);
Erik Språng490d76c2019-05-07 16:29:15949 }
950 }
951
Erik Språng6a0a5592021-06-15 17:04:24952 // Map from SSRC to vector of RTP sequence numbers that are indicated as
953 // lost by feedback, without being trailed by any received packets.
954 std::map<uint32_t, std::vector<uint16_t>> early_loss_detected_per_ssrc;
Erik Språng845c6aa2019-05-29 11:02:24955
Erik Språng6a0a5592021-06-15 17:04:24956 for (const StreamPacketInfo& packet : packet_feedback_vector) {
957 // Only include new media packets, not retransmissions/padding/fec.
958 if (!packet.received && packet.ssrc && !packet.is_retransmission) {
959 // Last known lost packet, might not be detectable as lost by remote
960 // jitter buffer.
961 early_loss_detected_per_ssrc[*packet.ssrc].push_back(
962 packet.rtp_sequence_number);
963 } else {
964 // Packet received, so any loss prior to this is already detectable.
965 early_loss_detected_per_ssrc.erase(*packet.ssrc);
Erik Språng845c6aa2019-05-29 11:02:24966 }
Erik Språng6a0a5592021-06-15 17:04:24967 }
Erik Språng845c6aa2019-05-29 11:02:24968
Erik Språng6a0a5592021-06-15 17:04:24969 for (const auto& kv : early_loss_detected_per_ssrc) {
970 const uint32_t ssrc = kv.first;
971 auto it = ssrc_to_rtp_module_.find(ssrc);
972 RTC_CHECK(it != ssrc_to_rtp_module_.end());
973 RTPSender* rtp_sender = it->second->RtpSender();
974 for (uint16_t sequence_number : kv.second) {
975 rtp_sender->ReSendPacket(sequence_number);
Erik Språng845c6aa2019-05-29 11:02:24976 }
Erik Språng6a0a5592021-06-15 17:04:24977 }
Erik Språng845c6aa2019-05-29 11:02:24978
Erik Språng490d76c2019-05-07 16:29:15979 for (const auto& kv : acked_packets_per_ssrc) {
980 const uint32_t ssrc = kv.first;
Erik Språnga9229042019-10-24 10:39:32981 auto it = ssrc_to_rtp_module_.find(ssrc);
982 if (it == ssrc_to_rtp_module_.end()) {
Erik Språng6a0a5592021-06-15 17:04:24983 // No media, likely FEC or padding. Ignore since there's no RTP history to
984 // clean up anyway.
Erik Språng490d76c2019-05-07 16:29:15985 continue;
986 }
987 rtc::ArrayView<const uint16_t> rtp_sequence_numbers(kv.second);
Erik Språng845c6aa2019-05-29 11:02:24988 it->second->OnPacketsAcknowledged(rtp_sequence_numbers);
Erik Språng490d76c2019-05-07 16:29:15989 }
Stefan Holmer64be7fa2018-10-04 13:21:55990}
991
992void RtpVideoSender::SetEncodingData(size_t width,
993 size_t height,
994 size_t num_temporal_layers) {
995 fec_controller_->SetEncodingData(width, height, num_temporal_layers,
996 rtp_config_.max_packet_size);
997}
Jakob Ivarsson9a12ee52020-11-26 15:04:18998
999DataRate RtpVideoSender::CalculateOverheadRate(DataRate data_rate,
1000 DataSize packet_size,
1001 DataSize overhead_per_packet,
1002 Frequency framerate) const {
1003 Frequency packet_rate = data_rate / packet_size;
1004 if (use_frame_rate_for_overhead_) {
1005 framerate = std::max(framerate, Frequency::Hertz(1));
1006 DataSize frame_size = data_rate / framerate;
1007 int packets_per_frame = ceil(frame_size / packet_size);
1008 packet_rate = packets_per_frame * framerate;
1009 }
1010 return packet_rate.RoundUpTo(Frequency::Hertz(1)) * overhead_per_packet;
1011}
1012
mflodman@webrtc.org02270cd2015-02-06 13:10:191013} // namespace webrtc