blob: 438fa1b81f88f04f2270e35ff01c7102943d3d74 [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"
Ali Tofigh641a1b12022-05-17 09:48:4620#include "absl/strings/string_view.h"
Erik Språng490d76c2019-05-07 16:29:1521#include "api/array_view.h"
Evan Shrubsole9b643d42022-10-07 14:22:4422#include "api/task_queue/task_queue_factory.h"
Niels Möller5fe95102019-03-04 15:49:2523#include "api/transport/field_trial_based_config.h"
Danil Chapovalov630c40d2023-07-17 14:42:4524#include "api/units/time_delta.h"
Danil Chapovalovb529b7a2019-11-27 12:59:4125#include "api/video_codecs/video_codec.h"
Stefan Holmerdbdb3a02018-07-17 14:03:4626#include "call/rtp_transport_controller_send_interface.h"
27#include "modules/pacing/packet_router.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3128#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
Tomas Gunnarssonfae05622020-06-03 06:54:3929#include "modules/rtp_rtcp/source/rtp_rtcp_impl2.h"
Stefan Holmerdbdb3a02018-07-17 14:03:4630#include "modules/rtp_rtcp/source/rtp_sender.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3131#include "modules/video_coding/include/video_codec_interface.h"
32#include "rtc_base/checks.h"
Stefan Holmerdbdb3a02018-07-17 14:03:4633#include "rtc_base/logging.h"
Marina Ciocea2e696602020-05-29 10:37:0134#include "rtc_base/task_queue.h"
Markus Handellfccb0522021-06-02 11:28:1035#include "rtc_base/trace_event.h"
mflodman@webrtc.org02270cd2015-02-06 13:10:1936
37namespace webrtc {
38
Niels Möller5fe95102019-03-04 15:49:2539namespace webrtc_internal_rtp_video_sender {
40
Erik Språngf87536c2020-03-05 09:14:0441RtpStreamSender::RtpStreamSender(
Tomas Gunnarssonf25761d2020-06-03 20:55:3342 std::unique_ptr<ModuleRtpRtcpImpl2> rtp_rtcp,
Erik Språngf87536c2020-03-05 09:14:0443 std::unique_ptr<RTPSenderVideo> sender_video,
44 std::unique_ptr<VideoFecGenerator> fec_generator)
45 : rtp_rtcp(std::move(rtp_rtcp)),
46 sender_video(std::move(sender_video)),
47 fec_generator(std::move(fec_generator)) {}
Niels Möller5fe95102019-03-04 15:49:2548
49RtpStreamSender::~RtpStreamSender() = default;
50
51} // namespace webrtc_internal_rtp_video_sender
52
kjellander02b3d272016-04-20 12:05:5453namespace {
Stefan Holmerdbdb3a02018-07-17 14:03:4654static const int kMinSendSidePacketHistorySize = 600;
Stefan Holmer64be7fa2018-10-04 13:21:5555// We don't do MTU discovery, so assume that we have the standard ethernet MTU.
56static const size_t kPathMTU = 1500;
Stefan Holmerdbdb3a02018-07-17 14:03:4657
Niels Möller5fe95102019-03-04 15:49:2558using webrtc_internal_rtp_video_sender::RtpStreamSender;
59
Ali Tofigh641a1b12022-05-17 09:48:4660bool PayloadTypeSupportsSkippingFecPackets(absl::string_view payload_name,
Jonas Orelande62c2f22022-03-29 09:04:4861 const FieldTrialsView& trials) {
Ali Tofigh641a1b12022-05-17 09:48:4662 const VideoCodecType codecType =
63 PayloadStringToCodecType(std::string(payload_name));
Erik Språngdc34a252019-10-04 13:17:2964 if (codecType == kVideoCodecVP8 || codecType == kVideoCodecVP9) {
65 return true;
66 }
67 if (codecType == kVideoCodecGeneric &&
Erik Språngcbc0cba2020-04-18 12:36:5968 absl::StartsWith(trials.Lookup("WebRTC-GenericPictureId"), "Enabled")) {
Erik Språngdc34a252019-10-04 13:17:2969 return true;
70 }
71 return false;
72}
73
74bool ShouldDisableRedAndUlpfec(bool flexfec_enabled,
Erik Språngcbc0cba2020-04-18 12:36:5975 const RtpConfig& rtp_config,
Jonas Orelande62c2f22022-03-29 09:04:4876 const FieldTrialsView& trials) {
Erik Språngdc34a252019-10-04 13:17:2977 // Consistency of NACK and RED+ULPFEC parameters is checked in this function.
78 const bool nack_enabled = rtp_config.nack.rtp_history_ms > 0;
79
80 // Shorthands.
81 auto IsRedEnabled = [&]() { return rtp_config.ulpfec.red_payload_type >= 0; };
82 auto IsUlpfecEnabled = [&]() {
83 return rtp_config.ulpfec.ulpfec_payload_type >= 0;
84 };
85
86 bool should_disable_red_and_ulpfec = false;
87
Erik Språngcbc0cba2020-04-18 12:36:5988 if (absl::StartsWith(trials.Lookup("WebRTC-DisableUlpFecExperiment"),
89 "Enabled")) {
Erik Språngdc34a252019-10-04 13:17:2990 RTC_LOG(LS_INFO) << "Experiment to disable sending ULPFEC is enabled.";
91 should_disable_red_and_ulpfec = true;
92 }
93
94 // If enabled, FlexFEC takes priority over RED+ULPFEC.
95 if (flexfec_enabled) {
96 if (IsUlpfecEnabled()) {
97 RTC_LOG(LS_INFO)
98 << "Both FlexFEC and ULPFEC are configured. Disabling ULPFEC.";
99 }
100 should_disable_red_and_ulpfec = true;
101 }
102
103 // Payload types without picture ID cannot determine that a stream is complete
104 // without retransmitting FEC, so using ULPFEC + NACK for H.264 (for instance)
105 // is a waste of bandwidth since FEC packets still have to be transmitted.
106 // Note that this is not the case with FlexFEC.
107 if (nack_enabled && IsUlpfecEnabled() &&
Erik Språngcbc0cba2020-04-18 12:36:59108 !PayloadTypeSupportsSkippingFecPackets(rtp_config.payload_name, trials)) {
Erik Språngdc34a252019-10-04 13:17:29109 RTC_LOG(LS_WARNING)
110 << "Transmitting payload type without picture ID using "
111 "NACK+ULPFEC is a waste of bandwidth since ULPFEC packets "
112 "also have to be retransmitted. Disabling ULPFEC.";
113 should_disable_red_and_ulpfec = true;
114 }
115
116 // Verify payload types.
117 if (IsUlpfecEnabled() ^ IsRedEnabled()) {
118 RTC_LOG(LS_WARNING)
119 << "Only RED or only ULPFEC enabled, but not both. Disabling both.";
120 should_disable_red_and_ulpfec = true;
121 }
122
123 return should_disable_red_and_ulpfec;
124}
125
Erik Språngf87536c2020-03-05 09:14:04126// TODO(brandtr): Update this function when we support multistream protection.
127std::unique_ptr<VideoFecGenerator> MaybeCreateFecGenerator(
128 Clock* clock,
129 const RtpConfig& rtp,
130 const std::map<uint32_t, RtpState>& suspended_ssrcs,
Erik Språngcbc0cba2020-04-18 12:36:59131 int simulcast_index,
Jonas Orelande62c2f22022-03-29 09:04:48132 const FieldTrialsView& trials) {
Erik Språngf87536c2020-03-05 09:14:04133 // If flexfec is configured that takes priority.
134 if (rtp.flexfec.payload_type >= 0) {
135 RTC_DCHECK_GE(rtp.flexfec.payload_type, 0);
136 RTC_DCHECK_LE(rtp.flexfec.payload_type, 127);
137 if (rtp.flexfec.ssrc == 0) {
138 RTC_LOG(LS_WARNING) << "FlexFEC is enabled, but no FlexFEC SSRC given. "
139 "Therefore disabling FlexFEC.";
140 return nullptr;
141 }
142 if (rtp.flexfec.protected_media_ssrcs.empty()) {
143 RTC_LOG(LS_WARNING)
144 << "FlexFEC is enabled, but no protected media SSRC given. "
145 "Therefore disabling FlexFEC.";
146 return nullptr;
147 }
148
149 if (rtp.flexfec.protected_media_ssrcs.size() > 1) {
150 RTC_LOG(LS_WARNING)
151 << "The supplied FlexfecConfig contained multiple protected "
152 "media streams, but our implementation currently only "
153 "supports protecting a single media stream. "
154 "To avoid confusion, disabling FlexFEC completely.";
155 return nullptr;
156 }
157
158 if (absl::c_find(rtp.flexfec.protected_media_ssrcs,
159 rtp.ssrcs[simulcast_index]) ==
160 rtp.flexfec.protected_media_ssrcs.end()) {
161 // Media SSRC not among flexfec protected SSRCs.
162 return nullptr;
163 }
164
165 const RtpState* rtp_state = nullptr;
166 auto it = suspended_ssrcs.find(rtp.flexfec.ssrc);
167 if (it != suspended_ssrcs.end()) {
168 rtp_state = &it->second;
169 }
170
171 RTC_DCHECK_EQ(1U, rtp.flexfec.protected_media_ssrcs.size());
172 return std::make_unique<FlexfecSender>(
173 rtp.flexfec.payload_type, rtp.flexfec.ssrc,
174 rtp.flexfec.protected_media_ssrcs[0], rtp.mid, rtp.extensions,
175 RTPSender::FecExtensionSizes(), rtp_state, clock);
176 } else if (rtp.ulpfec.red_payload_type >= 0 &&
177 rtp.ulpfec.ulpfec_payload_type >= 0 &&
Erik Språngcbc0cba2020-04-18 12:36:59178 !ShouldDisableRedAndUlpfec(/*flexfec_enabled=*/false, rtp,
179 trials)) {
Erik Språngf87536c2020-03-05 09:14:04180 // Flexfec not configured, but ulpfec is and is not disabled.
181 return std::make_unique<UlpfecGenerator>(
182 rtp.ulpfec.red_payload_type, rtp.ulpfec.ulpfec_payload_type, clock);
183 }
184
185 // Not a single FEC is given.
186 return nullptr;
187}
188
Niels Möller5fe95102019-03-04 15:49:25189std::vector<RtpStreamSender> CreateRtpStreamSenders(
Sebastian Jansson572c60f2019-03-04 17:30:41190 Clock* clock,
Johannes Kron9190b822018-10-29 10:22:05191 const RtpConfig& rtp_config,
Erik Språng7ea9b802019-10-16 17:03:38192 const RtpSenderObservers& observers,
Jiawei Ou55718122018-11-09 21:17:39193 int rtcp_report_interval_ms,
Stefan Holmerdbdb3a02018-07-17 14:03:46194 Transport* send_transport,
Stefan Holmerdbdb3a02018-07-17 14:03:46195 RtpTransportControllerSendInterface* transport,
Erik Språngf87536c2020-03-05 09:14:04196 const std::map<uint32_t, RtpState>& suspended_ssrcs,
Stefan Holmerdbdb3a02018-07-17 14:03:46197 RtcEventLog* event_log,
198 RateLimiter* retransmission_rate_limiter,
Benjamin Wright192eeec2018-10-18 00:27:25199 FrameEncryptorInterface* frame_encryptor,
Marina Cioceae77912b2020-02-27 15:16:55200 const CryptoOptions& crypto_options,
Erik Språngcbc0cba2020-04-18 12:36:59201 rtc::scoped_refptr<FrameTransformerInterface> frame_transformer,
Evan Shrubsole9b643d42022-10-07 14:22:44202 const FieldTrialsView& trials,
203 TaskQueueFactory* task_queue_factory) {
Amit Hilbuch0fc28432018-12-18 21:01:47204 RTC_DCHECK_GT(rtp_config.ssrcs.size(), 0);
Evan Shrubsole9b643d42022-10-07 14:22:44205 RTC_DCHECK(task_queue_factory);
Benjamin Wright192eeec2018-10-18 00:27:25206
Tomas Gunnarssonf25761d2020-06-03 20:55:33207 RtpRtcpInterface::Configuration configuration;
Sebastian Jansson572c60f2019-03-04 17:30:41208 configuration.clock = clock;
Stefan Holmerdbdb3a02018-07-17 14:03:46209 configuration.audio = false;
210 configuration.receiver_only = false;
211 configuration.outgoing_transport = send_transport;
Erik Språng7ea9b802019-10-16 17:03:38212 configuration.intra_frame_callback = observers.intra_frame_callback;
Elad Alon0a8562e2019-04-09 09:55:13213 configuration.rtcp_loss_notification_observer =
Erik Språng7ea9b802019-10-16 17:03:38214 observers.rtcp_loss_notification_observer;
Danil Chapovalov3e392542023-05-17 11:25:39215 configuration.network_link_rtcp_observer = transport->GetRtcpObserver();
Sebastian Janssone1795f42019-07-24 09:38:03216 configuration.network_state_estimate_observer =
217 transport->network_state_estimate_observer();
Stefan Holmerdbdb3a02018-07-17 14:03:46218 configuration.transport_feedback_callback =
219 transport->transport_feedback_observer();
Erik Språng7ea9b802019-10-16 17:03:38220 configuration.rtt_stats = observers.rtcp_rtt_stats;
221 configuration.rtcp_packet_type_counter_observer =
222 observers.rtcp_type_observer;
Danil Chapovalovbd74d5c2020-03-12 08:22:44223 configuration.report_block_data_observer =
224 observers.report_block_data_observer;
Stefan Holmerdbdb3a02018-07-17 14:03:46225 configuration.paced_sender = transport->packet_sender();
Erik Språng7ea9b802019-10-16 17:03:38226 configuration.send_bitrate_observer = observers.bitrate_observer;
Erik Språng7ea9b802019-10-16 17:03:38227 configuration.send_packet_observer = observers.send_packet_observer;
Stefan Holmerdbdb3a02018-07-17 14:03:46228 configuration.event_log = event_log;
229 configuration.retransmission_rate_limiter = retransmission_rate_limiter;
Erik Språng7ea9b802019-10-16 17:03:38230 configuration.rtp_stats_callback = observers.rtp_stats;
Benjamin Wright192eeec2018-10-18 00:27:25231 configuration.frame_encryptor = frame_encryptor;
232 configuration.require_frame_encryption =
233 crypto_options.sframe.require_frame_encryption;
Johannes Kron9190b822018-10-29 10:22:05234 configuration.extmap_allow_mixed = rtp_config.extmap_allow_mixed;
Jiawei Ou8b5d9d82018-11-16 00:44:37235 configuration.rtcp_report_interval_ms = rtcp_report_interval_ms;
Erik Språngcbc0cba2020-04-18 12:36:59236 configuration.field_trials = &trials;
Markus Handellc8c4a282023-05-08 14:46:21237 configuration.enable_send_packet_batching =
238 rtp_config.enable_send_packet_batching;
Benjamin Wright192eeec2018-10-18 00:27:25239
Niels Möller5fe95102019-03-04 15:49:25240 std::vector<RtpStreamSender> rtp_streams;
Erik Språngf87536c2020-03-05 09:14:04241
Erik Språng93f51892019-08-19 10:42:58242 RTC_DCHECK(rtp_config.rtx.ssrcs.empty() ||
Henrik Boströmf45ca372020-03-24 12:30:50243 rtp_config.rtx.ssrcs.size() == rtp_config.ssrcs.size());
Niels Mölleraf785d92022-05-31 08:45:41244
245 // Some streams could have been disabled, but the rids are still there.
246 // This will occur when simulcast has been disabled for a codec (e.g. VP9)
247 RTC_DCHECK(rtp_config.rids.empty() ||
248 rtp_config.rids.size() >= rtp_config.ssrcs.size());
249
Erik Språng93f51892019-08-19 10:42:58250 for (size_t i = 0; i < rtp_config.ssrcs.size(); ++i) {
Erik Språngf87536c2020-03-05 09:14:04251 RTPSenderVideo::Config video_config;
Erik Språng54d5d2c2019-08-20 15:22:36252 configuration.local_media_ssrc = rtp_config.ssrcs[i];
Erik Språngf87536c2020-03-05 09:14:04253
254 std::unique_ptr<VideoFecGenerator> fec_generator =
Erik Språngcbc0cba2020-04-18 12:36:59255 MaybeCreateFecGenerator(clock, rtp_config, suspended_ssrcs, i, trials);
Erik Språngf87536c2020-03-05 09:14:04256 configuration.fec_generator = fec_generator.get();
Niels Möller5fe95102019-03-04 15:49:25257
Henrik Boströmf45ca372020-03-24 12:30:50258 configuration.rtx_send_ssrc =
259 rtp_config.GetRtxSsrcAssociatedWithMediaSsrc(rtp_config.ssrcs[i]);
260 RTC_DCHECK_EQ(configuration.rtx_send_ssrc.has_value(),
261 !rtp_config.rtx.ssrcs.empty());
Erik Språng93f51892019-08-19 10:42:58262
Niels Mölleraf785d92022-05-31 08:45:41263 configuration.rid = (i < rtp_config.rids.size()) ? rtp_config.rids[i] : "";
264
Erik Språng3663f942020-02-07 09:05:15265 configuration.need_rtp_packet_infos = rtp_config.lntf.enabled;
266
Niels Moller2accc7d2021-01-12 15:54:16267 std::unique_ptr<ModuleRtpRtcpImpl2> rtp_rtcp(
268 ModuleRtpRtcpImpl2::Create(configuration));
Stefan Holmerdbdb3a02018-07-17 14:03:46269 rtp_rtcp->SetSendingStatus(false);
270 rtp_rtcp->SetSendingMediaStatus(false);
271 rtp_rtcp->SetRTCPStatus(RtcpMode::kCompound);
Erik Språngdc34a252019-10-04 13:17:29272 // Set NACK.
273 rtp_rtcp->SetStorePacketsStatus(true, kMinSendSidePacketHistorySize);
Niels Möller5fe95102019-03-04 15:49:25274
Erik Språngdc34a252019-10-04 13:17:29275 video_config.clock = configuration.clock;
276 video_config.rtp_sender = rtp_rtcp->RtpSender();
Erik Språngdc34a252019-10-04 13:17:29277 video_config.frame_encryptor = frame_encryptor;
278 video_config.require_frame_encryption =
279 crypto_options.sframe.require_frame_encryption;
Erik Språngcbc0cba2020-04-18 12:36:59280 video_config.field_trials = &trials;
Ying Wang764e89c2023-03-03 13:49:25281 video_config.enable_retransmit_all_layers =
Ying Wang371a82c2023-08-24 05:57:43282 !video_config.field_trials->IsDisabled(
Ying Wang764e89c2023-03-03 13:49:25283 "WebRTC-Video-EnableRetransmitAllLayers");
Erik Språngf87536c2020-03-05 09:14:04284
285 const bool using_flexfec =
286 fec_generator &&
287 fec_generator->GetFecType() == VideoFecGenerator::FecType::kFlexFec;
Erik Språngdc34a252019-10-04 13:17:29288 const bool should_disable_red_and_ulpfec =
Erik Språngcbc0cba2020-04-18 12:36:59289 ShouldDisableRedAndUlpfec(using_flexfec, rtp_config, trials);
Erik Språngf87536c2020-03-05 09:14:04290 if (!should_disable_red_and_ulpfec &&
291 rtp_config.ulpfec.red_payload_type != -1) {
Erik Språngdc34a252019-10-04 13:17:29292 video_config.red_payload_type = rtp_config.ulpfec.red_payload_type;
293 }
Erik Språng42108882020-05-05 12:51:09294 if (fec_generator) {
295 video_config.fec_type = fec_generator->GetFecType();
296 video_config.fec_overhead_bytes = fec_generator->MaxPacketOverhead();
297 }
Marina Cioceadc69fd22020-04-10 18:19:14298 video_config.frame_transformer = frame_transformer;
Evan Shrubsole9b643d42022-10-07 14:22:44299 video_config.task_queue_factory = task_queue_factory;
Erik Språngdc34a252019-10-04 13:17:29300 auto sender_video = std::make_unique<RTPSenderVideo>(video_config);
Erik Språngf87536c2020-03-05 09:14:04301 rtp_streams.emplace_back(std::move(rtp_rtcp), std::move(sender_video),
302 std::move(fec_generator));
Stefan Holmerdbdb3a02018-07-17 14:03:46303 }
Niels Möller5fe95102019-03-04 15:49:25304 return rtp_streams;
Stefan Holmerdbdb3a02018-07-17 14:03:46305}
306
Erik Språng6cf554e2019-10-02 18:55:39307absl::optional<VideoCodecType> GetVideoCodecType(const RtpConfig& config) {
Danil Chapovalovb529b7a2019-11-27 12:59:41308 if (config.raw_payload) {
309 return absl::nullopt;
Erik Språng6cf554e2019-10-02 18:55:39310 }
Danil Chapovalovb529b7a2019-11-27 12:59:41311 return PayloadStringToCodecType(config.payload_name);
Erik Språng6cf554e2019-10-02 18:55:39312}
Erik Språng42108882020-05-05 12:51:09313bool TransportSeqNumExtensionConfigured(const RtpConfig& config) {
314 return absl::c_any_of(config.extensions, [](const RtpExtension& ext) {
Sebastian Janssonc3eb9fd2020-01-29 16:42:52315 return ext.uri == RtpExtension::kTransportSequenceNumberUri;
316 });
317}
Danil Chapovalov0be18462021-01-20 11:11:29318
319// Returns true when some coded video sequence can be decoded starting with
320// this frame without requiring any previous frames.
321// e.g. it is the same as a key frame when spatial scalability is not used.
322// When spatial scalability is used, then it is true for layer frames of
323// a key frame without inter-layer dependencies.
324bool IsFirstFrameOfACodedVideoSequence(
325 const EncodedImage& encoded_image,
326 const CodecSpecificInfo* codec_specific_info) {
327 if (encoded_image._frameType != VideoFrameType::kVideoFrameKey) {
328 return false;
329 }
330
Danil Chapovalov37dfddd2021-01-27 18:24:23331 if (codec_specific_info != nullptr) {
332 if (codec_specific_info->generic_frame_info.has_value()) {
333 // This function is used before
334 // `codec_specific_info->generic_frame_info->frame_diffs` are calculated,
335 // so need to use a more complicated way to check for presence of the
336 // dependencies.
337 return absl::c_none_of(
338 codec_specific_info->generic_frame_info->encoder_buffers,
339 [](const CodecBufferUsage& buffer) { return buffer.referenced; });
340 }
341
342 if (codec_specific_info->codecType == VideoCodecType::kVideoCodecVP8 ||
343 codec_specific_info->codecType == VideoCodecType::kVideoCodecH264 ||
344 codec_specific_info->codecType == VideoCodecType::kVideoCodecGeneric) {
345 // These codecs do not support intra picture dependencies, so a frame
346 // marked as a key frame should be a key frame.
347 return true;
348 }
Danil Chapovalov0be18462021-01-20 11:11:29349 }
350
351 // Without depenedencies described in generic format do an educated guess.
352 // It might be wrong for VP9 with spatial layer 0 skipped or higher spatial
353 // layer not depending on the spatial layer 0. This corner case is unimportant
354 // for current usage of this helper function.
355
356 // Use <= to accept both 0 (i.e. the first) and nullopt (i.e. the only).
357 return encoded_image.SpatialIndex() <= 0;
358}
359
kjellander02b3d272016-04-20 12:05:54360} // namespace
361
Stefan Holmer9416ef82018-07-19 08:34:38362RtpVideoSender::RtpVideoSender(
Sebastian Jansson572c60f2019-03-04 17:30:41363 Clock* clock,
Tommi86952822021-11-29 09:26:40364 const std::map<uint32_t, RtpState>& suspended_ssrcs,
Stefan Holmer9416ef82018-07-19 08:34:38365 const std::map<uint32_t, RtpPayloadState>& states,
366 const RtpConfig& rtp_config,
Jiawei Ou55718122018-11-09 21:17:39367 int rtcp_report_interval_ms,
Stefan Holmer9416ef82018-07-19 08:34:38368 Transport* send_transport,
369 const RtpSenderObservers& observers,
370 RtpTransportControllerSendInterface* transport,
371 RtcEventLog* event_log,
Stefan Holmer64be7fa2018-10-04 13:21:55372 RateLimiter* retransmission_limiter,
Benjamin Wright192eeec2018-10-18 00:27:25373 std::unique_ptr<FecController> fec_controller,
374 FrameEncryptorInterface* frame_encryptor,
Marina Cioceae77912b2020-02-27 15:16:55375 const CryptoOptions& crypto_options,
Jonas Orelandc7f691a2022-03-09 14:12:07376 rtc::scoped_refptr<FrameTransformerInterface> frame_transformer,
Evan Shrubsole9b643d42022-10-07 14:22:44377 const FieldTrialsView& field_trials,
378 TaskQueueFactory* task_queue_factory)
Jonas Orelandc7f691a2022-03-09 14:12:07379 : field_trials_(field_trials),
Jakob Ivarsson9a12ee52020-11-26 15:04:18380 use_frame_rate_for_overhead_(absl::StartsWith(
381 field_trials_.Lookup("WebRTC-Video-UseFrameRateForOverhead"),
382 "Enabled")),
Sebastian Janssonc3eb9fd2020-01-29 16:42:52383 has_packet_feedback_(TransportSeqNumExtensionConfigured(rtp_config)),
Stefan Holmer64be7fa2018-10-04 13:21:55384 active_(false),
Stefan Holmer64be7fa2018-10-04 13:21:55385 fec_controller_(std::move(fec_controller)),
Elad Alon67daf712019-06-28 16:14:36386 fec_allowed_(true),
Erik Språng7ea9b802019-10-16 17:03:38387 rtp_streams_(CreateRtpStreamSenders(clock,
388 rtp_config,
389 observers,
390 rtcp_report_interval_ms,
391 send_transport,
Erik Språng7ea9b802019-10-16 17:03:38392 transport,
Tommi86952822021-11-29 09:26:40393 suspended_ssrcs,
Erik Språng7ea9b802019-10-16 17:03:38394 event_log,
395 retransmission_limiter,
Erik Språng7ea9b802019-10-16 17:03:38396 frame_encryptor,
Marina Cioceae77912b2020-02-27 15:16:55397 crypto_options,
Erik Språngcbc0cba2020-04-18 12:36:59398 std::move(frame_transformer),
Evan Shrubsole9b643d42022-10-07 14:22:44399 field_trials_,
400 task_queue_factory)),
Stefan Holmerdbdb3a02018-07-17 14:03:46401 rtp_config_(rtp_config),
Erik Språng6cf554e2019-10-02 18:55:39402 codec_type_(GetVideoCodecType(rtp_config)),
Stefan Holmer64be7fa2018-10-04 13:21:55403 transport_(transport),
404 transport_overhead_bytes_per_packet_(0),
Niels Möller949f0fd2019-01-29 08:44:24405 encoder_target_rate_bps_(0),
406 frame_counts_(rtp_config.ssrcs.size()),
Oleh Prypine8964902019-03-29 15:33:01407 frame_count_observer_(observers.frame_count_observer) {
Tommi2d319df2021-12-23 21:45:50408 transport_checker_.Detach();
Elad Alon62ce0352019-05-23 14:58:53409 RTC_DCHECK_EQ(rtp_config_.ssrcs.size(), rtp_streams_.size());
Per Kjellandere0b4cab2022-11-30 18:41:22410 if (has_packet_feedback_)
Sebastian Janssonc3eb9fd2020-01-29 16:42:52411 transport_->IncludeOverheadInPacedSender();
Artem Titovea240272021-07-26 10:40:21412 // SSRCs are assumed to be sorted in the same order as `rtp_modules`.
Elad Alon62ce0352019-05-23 14:58:53413 for (uint32_t ssrc : rtp_config_.ssrcs) {
Åsa Persson4bece9a2017-10-06 08:04:04414 // Restore state if it previously existed.
415 const RtpPayloadState* state = nullptr;
416 auto it = states.find(ssrc);
417 if (it != states.end()) {
418 state = &it->second;
philipel25d31ec2018-08-08 14:33:01419 shared_frame_id_ = std::max(shared_frame_id_, state->shared_frame_id);
Åsa Persson4bece9a2017-10-06 08:04:04420 }
Erik Språngcbc0cba2020-04-18 12:36:59421 params_.push_back(RtpPayloadParams(ssrc, state, field_trials_));
Åsa Persson4bece9a2017-10-06 08:04:04422 }
Stefan Holmerdbdb3a02018-07-17 14:03:46423
424 // RTP/RTCP initialization.
425
Stefan Holmerdbdb3a02018-07-17 14:03:46426 for (size_t i = 0; i < rtp_config_.extensions.size(); ++i) {
427 const std::string& extension = rtp_config_.extensions[i].uri;
428 int id = rtp_config_.extensions[i].id;
Stefan Holmerdbdb3a02018-07-17 14:03:46429 RTC_DCHECK(RtpExtension::IsSupportedForVideo(extension));
Niels Möller5fe95102019-03-04 15:49:25430 for (const RtpStreamSender& stream : rtp_streams_) {
Sebastian Janssonf39c8152019-10-14 15:32:21431 stream.rtp_rtcp->RegisterRtpHeaderExtension(extension, id);
Stefan Holmerdbdb3a02018-07-17 14:03:46432 }
433 }
434
Tommi86952822021-11-29 09:26:40435 ConfigureSsrcs(suspended_ssrcs);
Stefan Holmerdbdb3a02018-07-17 14:03:46436
Elad Alon62ce0352019-05-23 14:58:53437 if (!rtp_config_.mid.empty()) {
Niels Möller5fe95102019-03-04 15:49:25438 for (const RtpStreamSender& stream : rtp_streams_) {
Elad Alon62ce0352019-05-23 14:58:53439 stream.rtp_rtcp->SetMid(rtp_config_.mid);
Stefan Holmerdbdb3a02018-07-17 14:03:46440 }
441 }
442
Erik Språngf87536c2020-03-05 09:14:04443 bool fec_enabled = false;
Niels Möller5fe95102019-03-04 15:49:25444 for (const RtpStreamSender& stream : rtp_streams_) {
Amit Hilbuch38e6c662019-03-09 00:17:21445 // Simulcast has one module for each layer. Set the CNAME on all modules.
Elad Alon62ce0352019-05-23 14:58:53446 stream.rtp_rtcp->SetCNAME(rtp_config_.c_name.c_str());
Elad Alon62ce0352019-05-23 14:58:53447 stream.rtp_rtcp->SetMaxRtpPacketSize(rtp_config_.max_packet_size);
448 stream.rtp_rtcp->RegisterSendPayloadFrequency(rtp_config_.payload_type,
Niels Möller5fe95102019-03-04 15:49:25449 kVideoPayloadTypeFrequency);
Erik Språngf87536c2020-03-05 09:14:04450 if (stream.fec_generator != nullptr) {
451 fec_enabled = true;
452 }
Stefan Holmerdbdb3a02018-07-17 14:03:46453 }
Stefan Holmer64be7fa2018-10-04 13:21:55454 // Currently, both ULPFEC and FlexFEC use the same FEC rate calculation logic,
455 // so enable that logic if either of those FEC schemes are enabled.
Erik Språngf87536c2020-03-05 09:14:04456 fec_controller_->SetProtectionMethod(fec_enabled, NackEnabled());
Stefan Holmer64be7fa2018-10-04 13:21:55457
458 fec_controller_->SetProtectionCallback(this);
Erik Språngb6bbdeb2021-08-13 14:12:41459
460 // Construction happens on the worker thread (see Call::CreateVideoSendStream)
461 // but subseqeuent calls to the RTP state will happen on one of two threads:
462 // * The pacer thread for actually sending packets.
463 // * The transport thread when tearing down and quering GetRtpState().
464 // Detach thread checkers.
465 for (const RtpStreamSender& stream : rtp_streams_) {
466 stream.rtp_rtcp->OnPacketSendingThreadSwitched();
467 }
Per83d09102016-04-15 12:59:13468}
mflodman@webrtc.org02270cd2015-02-06 13:10:19469
Stefan Holmer9416ef82018-07-19 08:34:38470RtpVideoSender::~RtpVideoSender() {
Tommi2d319df2021-12-23 21:45:50471 // TODO(bugs.webrtc.org/13517): Remove once RtpVideoSender gets deleted on the
472 // transport task queue.
473 transport_checker_.Detach();
474
Erik Språng61d17732021-02-24 15:15:30475 SetActiveModulesLocked(
476 std::vector<bool>(rtp_streams_.size(), /*active=*/false));
Tommi6fba6b72022-01-28 08:00:01477
478 RTC_DCHECK(!registered_for_feedback_);
Stefan Holmerdbdb3a02018-07-17 14:03:46479}
480
Per Kjellander59ade012022-12-02 08:09:37481void RtpVideoSender::Stop() {
Tommi2d319df2021-12-23 21:45:50482 RTC_DCHECK_RUN_ON(&transport_checker_);
Markus Handell8fe932a2020-07-06 15:41:35483 MutexLock lock(&mutex_);
Per Kjellander59ade012022-12-02 08:09:37484 if (!active_)
Peter Boström8b79b072016-02-26 15:31:37485 return;
Tommi6fba6b72022-01-28 08:00:01486
Per Kjellander59ade012022-12-02 08:09:37487 const std::vector<bool> active_modules(rtp_streams_.size(), false);
Markus Handell2b7d9692020-05-14 13:03:40488 SetActiveModulesLocked(active_modules);
Seth Hampsoncc7125f2018-02-02 16:46:16489}
Per512ecb32016-09-23 13:52:06490
Per Kjellander59ade012022-12-02 08:09:37491void RtpVideoSender::SetActiveModules(const std::vector<bool>& active_modules) {
Tommi2d319df2021-12-23 21:45:50492 RTC_DCHECK_RUN_ON(&transport_checker_);
Markus Handell8fe932a2020-07-06 15:41:35493 MutexLock lock(&mutex_);
Markus Handell2b7d9692020-05-14 13:03:40494 return SetActiveModulesLocked(active_modules);
495}
496
497void RtpVideoSender::SetActiveModulesLocked(
Per Kjellander59ade012022-12-02 08:09:37498 const std::vector<bool>& active_modules) {
Tommi2d319df2021-12-23 21:45:50499 RTC_DCHECK_RUN_ON(&transport_checker_);
Henrik Boström0145db42023-07-26 12:01:59500 RTC_CHECK_EQ(rtp_streams_.size(), active_modules.size());
Seth Hampsoncc7125f2018-02-02 16:46:16501 active_ = false;
502 for (size_t i = 0; i < active_modules.size(); ++i) {
503 if (active_modules[i]) {
504 active_ = true;
505 }
Erik Språng61d17732021-02-24 15:15:30506
Erik Språngc96aa302021-02-25 16:05:21507 RtpRtcpInterface& rtp_module = *rtp_streams_[i].rtp_rtcp;
Per Kjellanderfb8641c2022-08-11 07:25:00508 const bool was_active = rtp_module.Sending();
Erik Språng61d17732021-02-24 15:15:30509 const bool should_be_active = active_modules[i];
510
Erik Språngc96aa302021-02-25 16:05:21511 rtp_module.SetSendingStatus(active_modules[i]);
Erik Språng61d17732021-02-24 15:15:30512
513 if (was_active && !should_be_active) {
514 // Disabling media, remove from packet router map to reduce size and
515 // prevent any stray packets in the pacer from asynchronously arriving
516 // to a disabled module.
Erik Språngc96aa302021-02-25 16:05:21517 transport_->packet_router()->RemoveSendRtpModule(&rtp_module);
Erik Språng1b11b582022-12-09 20:38:44518
519 // Clear the pacer queue of any packets pertaining to this module.
520 transport_->packet_sender()->RemovePacketsForSsrc(rtp_module.SSRC());
521 if (rtp_module.RtxSsrc().has_value()) {
522 transport_->packet_sender()->RemovePacketsForSsrc(
523 *rtp_module.RtxSsrc());
524 }
525 if (rtp_module.FlexfecSsrc().has_value()) {
526 transport_->packet_sender()->RemovePacketsForSsrc(
527 *rtp_module.FlexfecSsrc());
528 }
Erik Språng61d17732021-02-24 15:15:30529 }
530
Seth Hampsoncc7125f2018-02-02 16:46:16531 // If set to false this module won't send media.
Erik Språngc96aa302021-02-25 16:05:21532 rtp_module.SetSendingMediaStatus(active_modules[i]);
Erik Språng61d17732021-02-24 15:15:30533
534 if (!was_active && should_be_active) {
535 // Turning on media, register with packet router.
Erik Språngc96aa302021-02-25 16:05:21536 transport_->packet_router()->AddSendRtpModule(&rtp_module,
537 /*remb_candidate=*/true);
Erik Språng61d17732021-02-24 15:15:30538 }
Per512ecb32016-09-23 13:52:06539 }
Per Kjellander59ade012022-12-02 08:09:37540 if (!active_) {
541 auto* feedback_provider = transport_->GetStreamFeedbackProvider();
542 if (registered_for_feedback_) {
543 feedback_provider->DeRegisterStreamFeedbackObserver(this);
544 registered_for_feedback_ = false;
545 }
546 } else if (!registered_for_feedback_) {
547 auto* feedback_provider = transport_->GetStreamFeedbackProvider();
548 feedback_provider->RegisterStreamFeedbackObserver(rtp_config_.ssrcs, this);
549 registered_for_feedback_ = true;
550 }
mflodman@webrtc.org02270cd2015-02-06 13:10:19551}
552
Stefan Holmer9416ef82018-07-19 08:34:38553bool RtpVideoSender::IsActive() {
Tommi2d319df2021-12-23 21:45:50554 RTC_DCHECK_RUN_ON(&transport_checker_);
Markus Handell8fe932a2020-07-06 15:41:35555 MutexLock lock(&mutex_);
Markus Handell2b7d9692020-05-14 13:03:40556 return IsActiveLocked();
557}
558
559bool RtpVideoSender::IsActiveLocked() {
Niels Möller5fe95102019-03-04 15:49:25560 return active_ && !rtp_streams_.empty();
mflodman@webrtc.org02270cd2015-02-06 13:10:19561}
562
Stefan Holmer9416ef82018-07-19 08:34:38563EncodedImageCallback::Result RtpVideoSender::OnEncodedImage(
Sergey Ulanov525df3f2016-08-03 00:46:41564 const EncodedImage& encoded_image,
Danil Chapovalov383f2cf2020-08-12 09:06:53565 const CodecSpecificInfo* codec_specific_info) {
Niels Möller77536a22019-01-15 07:50:01566 fec_controller_->UpdateWithEncodedData(encoded_image.size(),
Stefan Holmer64be7fa2018-10-04 13:21:55567 encoded_image._frameType);
Markus Handell8fe932a2020-07-06 15:41:35568 MutexLock lock(&mutex_);
Niels Möller5fe95102019-03-04 15:49:25569 RTC_DCHECK(!rtp_streams_.empty());
Per512ecb32016-09-23 13:52:06570 if (!active_)
Sergey Ulanov525df3f2016-08-03 00:46:41571 return Result(Result::ERROR_SEND_FAILED);
mflodman@webrtc.org50e28162015-02-23 07:45:11572
philipelbf2b6202018-08-27 12:33:18573 shared_frame_id_++;
Henrik Boströmc5a4c932023-02-21 14:53:43574 size_t simulcast_index = encoded_image.SimulcastIndex().value_or(0);
Henrik Boström2e540a22023-02-15 13:48:09575 RTC_DCHECK_LT(simulcast_index, rtp_streams_.size());
Niels Möllerbb894ff2018-03-15 11:28:53576
Niels Möller5fe95102019-03-04 15:49:25577 uint32_t rtp_timestamp =
578 encoded_image.Timestamp() +
Henrik Boström2e540a22023-02-15 13:48:09579 rtp_streams_[simulcast_index].rtp_rtcp->StartTimestamp();
Niels Möller5fe95102019-03-04 15:49:25580
581 // RTCPSender has it's own copy of the timestamp offset, added in
582 // RTCPSender::BuildSR, hence we must not add the in the offset for this call.
583 // TODO(nisse): Delete RTCPSender:timestamp_offset_, and see if we can confine
584 // knowledge of the offset to a single place.
Henrik Boström2e540a22023-02-15 13:48:09585 if (!rtp_streams_[simulcast_index].rtp_rtcp->OnSendingRtpFrame(
Niels Möller5fe95102019-03-04 15:49:25586 encoded_image.Timestamp(), encoded_image.capture_time_ms_,
587 rtp_config_.payload_type,
Niels Möller8f7ce222019-03-21 14:43:58588 encoded_image._frameType == VideoFrameType::kVideoFrameKey)) {
Seth Hampsoncc7125f2018-02-02 16:46:16589 // The payload router could be active but this module isn't sending.
590 return Result(Result::ERROR_SEND_FAILED);
591 }
Elad Alonb64af4b2019-06-05 09:39:37592
Danil Chapovalov630c40d2023-07-17 14:42:45593 TimeDelta expected_retransmission_time = TimeDelta::PlusInfinity();
Elad Alonb64af4b2019-06-05 09:39:37594 if (encoded_image.RetransmissionAllowed()) {
Danil Chapovalov630c40d2023-07-17 14:42:45595 expected_retransmission_time =
596 rtp_streams_[simulcast_index].rtp_rtcp->ExpectedRetransmissionTime();
Elad Alonb64af4b2019-06-05 09:39:37597 }
Niels Möller949f0fd2019-01-29 08:44:24598
Danil Chapovalov0be18462021-01-20 11:11:29599 if (IsFirstFrameOfACodedVideoSequence(encoded_image, codec_specific_info)) {
Emil Lundmark6c81a422022-05-18 15:13:34600 // In order to use the dependency descriptor RTP header extension:
601 // - Pass along any `FrameDependencyStructure` templates produced by the
602 // encoder adapter.
603 // - If none were produced the `RtpPayloadParams::*ToGeneric` for the
604 // particular codec have simulated a dependency structure, so provide a
605 // minimal set of templates.
606 // - Otherwise, don't pass along any templates at all which will disable
607 // the generation of a dependency descriptor.
Henrik Boström2e540a22023-02-15 13:48:09608 RTPSenderVideo& sender_video = *rtp_streams_[simulcast_index].sender_video;
Danil Chapovalov748550d2021-04-29 09:42:54609 if (codec_specific_info && codec_specific_info->template_structure) {
610 sender_video.SetVideoStructure(&*codec_specific_info->template_structure);
Danil Chapovalov5b298ab2022-06-08 09:18:51611 } else if (absl::optional<FrameDependencyStructure> structure =
Henrik Boström2e540a22023-02-15 13:48:09612 params_[simulcast_index].GenericStructure(
Danil Chapovalov5b298ab2022-06-08 09:18:51613 codec_specific_info)) {
614 sender_video.SetVideoStructure(&*structure);
Danil Chapovalov748550d2021-04-29 09:42:54615 } else {
616 sender_video.SetVideoStructure(nullptr);
617 }
Danil Chapovalov2272f202020-02-18 11:09:43618 }
619
Henrik Boström2e540a22023-02-15 13:48:09620 bool send_result =
621 rtp_streams_[simulcast_index].sender_video->SendEncodedImage(
622 rtp_config_.payload_type, codec_type_, rtp_timestamp, encoded_image,
623 params_[simulcast_index].GetRtpVideoHeader(
624 encoded_image, codec_specific_info, shared_frame_id_),
Danil Chapovalov630c40d2023-07-17 14:42:45625 expected_retransmission_time);
Niels Möller949f0fd2019-01-29 08:44:24626 if (frame_count_observer_) {
Henrik Boström2e540a22023-02-15 13:48:09627 FrameCounts& counts = frame_counts_[simulcast_index];
Niels Möller8f7ce222019-03-21 14:43:58628 if (encoded_image._frameType == VideoFrameType::kVideoFrameKey) {
Niels Möller949f0fd2019-01-29 08:44:24629 ++counts.key_frames;
Niels Möller8f7ce222019-03-21 14:43:58630 } else if (encoded_image._frameType == VideoFrameType::kVideoFrameDelta) {
Niels Möller949f0fd2019-01-29 08:44:24631 ++counts.delta_frames;
632 } else {
Niels Möller8f7ce222019-03-21 14:43:58633 RTC_DCHECK(encoded_image._frameType == VideoFrameType::kEmptyFrame);
Niels Möller949f0fd2019-01-29 08:44:24634 }
Henrik Boström2e540a22023-02-15 13:48:09635 frame_count_observer_->FrameCountUpdated(
636 counts, rtp_config_.ssrcs[simulcast_index]);
Niels Möller949f0fd2019-01-29 08:44:24637 }
sergeyu7b9feee2016-11-18 00:16:14638 if (!send_result)
Sergey Ulanov525df3f2016-08-03 00:46:41639 return Result(Result::ERROR_SEND_FAILED);
640
Niels Möller5fe95102019-03-04 15:49:25641 return Result(Result::OK, rtp_timestamp);
mflodman@webrtc.orga4ef2ce2015-02-12 09:54:18642}
643
Stefan Holmer9416ef82018-07-19 08:34:38644void RtpVideoSender::OnBitrateAllocationUpdated(
Erik Språng566124a2018-04-23 10:32:22645 const VideoBitrateAllocation& bitrate) {
Tommi2d319df2021-12-23 21:45:50646 RTC_DCHECK_RUN_ON(&transport_checker_);
Markus Handell8fe932a2020-07-06 15:41:35647 MutexLock lock(&mutex_);
Markus Handell2b7d9692020-05-14 13:03:40648 if (IsActiveLocked()) {
Oleh Prypine8964902019-03-29 15:33:01649 if (rtp_streams_.size() == 1) {
sprang1a646ee2016-12-01 14:34:11650 // If spatial scalability is enabled, it is covered by a single stream.
Niels Möller5fe95102019-03-04 15:49:25651 rtp_streams_[0].rtp_rtcp->SetVideoBitrateAllocation(bitrate);
sprang1a646ee2016-12-01 14:34:11652 } else {
Stefan Holmerf7044682018-07-17 08:16:41653 std::vector<absl::optional<VideoBitrateAllocation>> layer_bitrates =
654 bitrate.GetSimulcastAllocations();
Erik Språng566124a2018-04-23 10:32:22655 // Simulcast is in use, split the VideoBitrateAllocation into one struct
656 // per rtp stream, moving over the temporal layer allocation.
Niels Möller5fe95102019-03-04 15:49:25657 for (size_t i = 0; i < rtp_streams_.size(); ++i) {
Stefan Holmerf7044682018-07-17 08:16:41658 // The next spatial layer could be used if the current one is
659 // inactive.
660 if (layer_bitrates[i]) {
Niels Möller5fe95102019-03-04 15:49:25661 rtp_streams_[i].rtp_rtcp->SetVideoBitrateAllocation(
662 *layer_bitrates[i]);
Ilya Nikolaevskiyb0588e62018-08-27 12:12:27663 } else {
664 // Signal a 0 bitrate on a simulcast stream.
Niels Möller5fe95102019-03-04 15:49:25665 rtp_streams_[i].rtp_rtcp->SetVideoBitrateAllocation(
666 VideoBitrateAllocation());
Seth Hampson46e31ba2018-01-18 18:39:54667 }
sprang1a646ee2016-12-01 14:34:11668 }
669 }
670 }
671}
Per Kjellanderaf704182020-10-16 08:30:40672void RtpVideoSender::OnVideoLayersAllocationUpdated(
673 const VideoLayersAllocation& allocation) {
674 MutexLock lock(&mutex_);
675 if (IsActiveLocked()) {
676 for (size_t i = 0; i < rtp_streams_.size(); ++i) {
677 VideoLayersAllocation stream_allocation = allocation;
678 stream_allocation.rtp_stream_index = i;
679 rtp_streams_[i].sender_video->SetVideoLayersAllocation(
680 std::move(stream_allocation));
Per Kjellanderfb8641c2022-08-11 07:25:00681 // Only send video frames on the rtp module if the encoder is configured
682 // to send. This is to prevent stray frames to be sent after an encoder
683 // has been reconfigured.
684 rtp_streams_[i].rtp_rtcp->SetSendingMediaStatus(
685 absl::c_any_of(allocation.active_spatial_layers,
686 [&i](const VideoLayersAllocation::SpatialLayer layer) {
687 return layer.rtp_stream_index == static_cast<int>(i);
688 }));
Per Kjellanderaf704182020-10-16 08:30:40689 }
690 }
691}
sprang1a646ee2016-12-01 14:34:11692
Stefan Holmer9416ef82018-07-19 08:34:38693bool RtpVideoSender::NackEnabled() const {
Stefan Holmerdbdb3a02018-07-17 14:03:46694 const bool nack_enabled = rtp_config_.nack.rtp_history_ms > 0;
695 return nack_enabled;
696}
697
Stefan Holmerf5bbb292023-04-28 11:33:42698DataRate RtpVideoSender::GetPostEncodeOverhead() const {
699 DataRate post_encode_overhead = DataRate::Zero();
Niels Möller5fe95102019-03-04 15:49:25700 for (size_t i = 0; i < rtp_streams_.size(); ++i) {
701 if (rtp_streams_[i].rtp_rtcp->SendingMedia()) {
Stefan Holmerf5bbb292023-04-28 11:33:42702 post_encode_overhead +=
703 rtp_streams_[i].sender_video->PostEncodeOverhead();
Erik Språng482b3ef2019-01-08 15:19:11704 }
705 }
Stefan Holmerf5bbb292023-04-28 11:33:42706 return post_encode_overhead;
Erik Språng482b3ef2019-01-08 15:19:11707}
708
Stefan Holmer9416ef82018-07-19 08:34:38709void RtpVideoSender::DeliverRtcp(const uint8_t* packet, size_t length) {
Stefan Holmerdbdb3a02018-07-17 14:03:46710 // Runs on a network thread.
Niels Möller5fe95102019-03-04 15:49:25711 for (const RtpStreamSender& stream : rtp_streams_)
Harald Alvestrand1f206b82023-02-01 11:12:46712 stream.rtp_rtcp->IncomingRtcpPacket(rtc::MakeArrayView(packet, length));
Stefan Holmerdbdb3a02018-07-17 14:03:46713}
714
Tommi86952822021-11-29 09:26:40715void RtpVideoSender::ConfigureSsrcs(
716 const std::map<uint32_t, RtpState>& suspended_ssrcs) {
Stefan Holmerdbdb3a02018-07-17 14:03:46717 // Configure regular SSRCs.
Erik Språnga9229042019-10-24 10:39:32718 RTC_CHECK(ssrc_to_rtp_module_.empty());
Elad Alon62ce0352019-05-23 14:58:53719 for (size_t i = 0; i < rtp_config_.ssrcs.size(); ++i) {
720 uint32_t ssrc = rtp_config_.ssrcs[i];
Tomas Gunnarssonf25761d2020-06-03 20:55:33721 RtpRtcpInterface* const rtp_rtcp = rtp_streams_[i].rtp_rtcp.get();
Stefan Holmerdbdb3a02018-07-17 14:03:46722
723 // Restore RTP state if previous existed.
Tommi86952822021-11-29 09:26:40724 auto it = suspended_ssrcs.find(ssrc);
725 if (it != suspended_ssrcs.end())
Stefan Holmerdbdb3a02018-07-17 14:03:46726 rtp_rtcp->SetRtpState(it->second);
Erik Språng490d76c2019-05-07 16:29:15727
Erik Språnga9229042019-10-24 10:39:32728 ssrc_to_rtp_module_[ssrc] = rtp_rtcp;
Stefan Holmerdbdb3a02018-07-17 14:03:46729 }
730
731 // Set up RTX if available.
Elad Alon62ce0352019-05-23 14:58:53732 if (rtp_config_.rtx.ssrcs.empty())
Stefan Holmerdbdb3a02018-07-17 14:03:46733 return;
734
Elad Alon62ce0352019-05-23 14:58:53735 RTC_DCHECK_EQ(rtp_config_.rtx.ssrcs.size(), rtp_config_.ssrcs.size());
736 for (size_t i = 0; i < rtp_config_.rtx.ssrcs.size(); ++i) {
737 uint32_t ssrc = rtp_config_.rtx.ssrcs[i];
Tomas Gunnarssonf25761d2020-06-03 20:55:33738 RtpRtcpInterface* const rtp_rtcp = rtp_streams_[i].rtp_rtcp.get();
Tommi86952822021-11-29 09:26:40739 auto it = suspended_ssrcs.find(ssrc);
740 if (it != suspended_ssrcs.end())
Stefan Holmerdbdb3a02018-07-17 14:03:46741 rtp_rtcp->SetRtxState(it->second);
742 }
743
744 // Configure RTX payload types.
Elad Alon62ce0352019-05-23 14:58:53745 RTC_DCHECK_GE(rtp_config_.rtx.payload_type, 0);
Niels Möller5fe95102019-03-04 15:49:25746 for (const RtpStreamSender& stream : rtp_streams_) {
Elad Alon62ce0352019-05-23 14:58:53747 stream.rtp_rtcp->SetRtxSendPayloadType(rtp_config_.rtx.payload_type,
748 rtp_config_.payload_type);
Niels Möller5fe95102019-03-04 15:49:25749 stream.rtp_rtcp->SetRtxSendStatus(kRtxRetransmitted |
750 kRtxRedundantPayloads);
Stefan Holmerdbdb3a02018-07-17 14:03:46751 }
Elad Alon62ce0352019-05-23 14:58:53752 if (rtp_config_.ulpfec.red_payload_type != -1 &&
753 rtp_config_.ulpfec.red_rtx_payload_type != -1) {
Niels Möller5fe95102019-03-04 15:49:25754 for (const RtpStreamSender& stream : rtp_streams_) {
755 stream.rtp_rtcp->SetRtxSendPayloadType(
Elad Alon62ce0352019-05-23 14:58:53756 rtp_config_.ulpfec.red_rtx_payload_type,
757 rtp_config_.ulpfec.red_payload_type);
Stefan Holmerdbdb3a02018-07-17 14:03:46758 }
759 }
760}
761
Stefan Holmer9416ef82018-07-19 08:34:38762void RtpVideoSender::OnNetworkAvailability(bool network_available) {
Niels Möller5fe95102019-03-04 15:49:25763 for (const RtpStreamSender& stream : rtp_streams_) {
764 stream.rtp_rtcp->SetRTCPStatus(network_available ? rtp_config_.rtcp_mode
765 : RtcpMode::kOff);
Stefan Holmerdbdb3a02018-07-17 14:03:46766 }
767}
768
Stefan Holmer9416ef82018-07-19 08:34:38769std::map<uint32_t, RtpState> RtpVideoSender::GetRtpStates() const {
Stefan Holmerdbdb3a02018-07-17 14:03:46770 std::map<uint32_t, RtpState> rtp_states;
771
772 for (size_t i = 0; i < rtp_config_.ssrcs.size(); ++i) {
773 uint32_t ssrc = rtp_config_.ssrcs[i];
Niels Möller5fe95102019-03-04 15:49:25774 RTC_DCHECK_EQ(ssrc, rtp_streams_[i].rtp_rtcp->SSRC());
775 rtp_states[ssrc] = rtp_streams_[i].rtp_rtcp->GetRtpState();
Erik Språngf87536c2020-03-05 09:14:04776
Erik Språng42108882020-05-05 12:51:09777 // Only happens during shutdown, when RTP module is already inactive,
778 // so OK to call fec generator here.
779 if (rtp_streams_[i].fec_generator) {
780 absl::optional<RtpState> fec_state =
781 rtp_streams_[i].fec_generator->GetRtpState();
782 if (fec_state) {
783 uint32_t ssrc = rtp_config_.flexfec.ssrc;
784 rtp_states[ssrc] = *fec_state;
785 }
Erik Språngf87536c2020-03-05 09:14:04786 }
Stefan Holmerdbdb3a02018-07-17 14:03:46787 }
788
789 for (size_t i = 0; i < rtp_config_.rtx.ssrcs.size(); ++i) {
790 uint32_t ssrc = rtp_config_.rtx.ssrcs[i];
Niels Möller5fe95102019-03-04 15:49:25791 rtp_states[ssrc] = rtp_streams_[i].rtp_rtcp->GetRtxState();
Stefan Holmerdbdb3a02018-07-17 14:03:46792 }
793
Stefan Holmerdbdb3a02018-07-17 14:03:46794 return rtp_states;
795}
796
Stefan Holmer9416ef82018-07-19 08:34:38797std::map<uint32_t, RtpPayloadState> RtpVideoSender::GetRtpPayloadStates()
798 const {
Markus Handell8fe932a2020-07-06 15:41:35799 MutexLock lock(&mutex_);
Stefan Holmerdbdb3a02018-07-17 14:03:46800 std::map<uint32_t, RtpPayloadState> payload_states;
801 for (const auto& param : params_) {
802 payload_states[param.ssrc()] = param.state();
philipel25d31ec2018-08-08 14:33:01803 payload_states[param.ssrc()].shared_frame_id = shared_frame_id_;
Stefan Holmerdbdb3a02018-07-17 14:03:46804 }
805 return payload_states;
806}
Stefan Holmer64be7fa2018-10-04 13:21:55807
808void RtpVideoSender::OnTransportOverheadChanged(
809 size_t transport_overhead_bytes_per_packet) {
Markus Handell8fe932a2020-07-06 15:41:35810 MutexLock lock(&mutex_);
Stefan Holmer64be7fa2018-10-04 13:21:55811 transport_overhead_bytes_per_packet_ = transport_overhead_bytes_per_packet;
812
813 size_t max_rtp_packet_size =
814 std::min(rtp_config_.max_packet_size,
815 kPathMTU - transport_overhead_bytes_per_packet_);
Niels Möller5fe95102019-03-04 15:49:25816 for (const RtpStreamSender& stream : rtp_streams_) {
817 stream.rtp_rtcp->SetMaxRtpPacketSize(max_rtp_packet_size);
Stefan Holmer64be7fa2018-10-04 13:21:55818 }
819}
820
Sebastian Jansson82ed2e82019-10-15 13:58:37821void RtpVideoSender::OnBitrateUpdated(BitrateAllocationUpdate update,
Stefan Holmer64be7fa2018-10-04 13:21:55822 int framerate) {
823 // Substract overhead from bitrate.
Markus Handell8fe932a2020-07-06 15:41:35824 MutexLock lock(&mutex_);
Erik Språng04e1bab2020-05-07 16:18:32825 size_t num_active_streams = 0;
826 size_t overhead_bytes_per_packet = 0;
827 for (const auto& stream : rtp_streams_) {
828 if (stream.rtp_rtcp->SendingMedia()) {
829 overhead_bytes_per_packet += stream.rtp_rtcp->ExpectedPerPacketOverhead();
830 ++num_active_streams;
831 }
832 }
833 if (num_active_streams > 1) {
834 overhead_bytes_per_packet /= num_active_streams;
835 }
836
Danil Chapovalovcad3e0e2020-02-17 17:46:07837 DataSize packet_overhead = DataSize::Bytes(
Erik Språng04e1bab2020-05-07 16:18:32838 overhead_bytes_per_packet + transport_overhead_bytes_per_packet_);
Danil Chapovalovcad3e0e2020-02-17 17:46:07839 DataSize max_total_packet_size = DataSize::Bytes(
Sebastian Janssoncf41eb12019-06-10 09:30:59840 rtp_config_.max_packet_size + transport_overhead_bytes_per_packet_);
Sebastian Jansson82ed2e82019-10-15 13:58:37841 uint32_t payload_bitrate_bps = update.target_bitrate.bps();
Per Kjellandere0b4cab2022-11-30 18:41:22842 if (has_packet_feedback_) {
Jakob Ivarsson9a12ee52020-11-26 15:04:18843 DataRate overhead_rate =
844 CalculateOverheadRate(update.target_bitrate, max_total_packet_size,
845 packet_overhead, Frequency::Hertz(framerate));
Sebastian Janssoncf41eb12019-06-10 09:30:59846 // TODO(srte): We probably should not accept 0 payload bitrate here.
Sebastian Jansson82ed2e82019-10-15 13:58:37847 payload_bitrate_bps = rtc::saturated_cast<uint32_t>(payload_bitrate_bps -
848 overhead_rate.bps());
Stefan Holmer64be7fa2018-10-04 13:21:55849 }
850
851 // Get the encoder target rate. It is the estimated network rate -
852 // protection overhead.
Sebastian Jansson82ed2e82019-10-15 13:58:37853 // TODO(srte): We should multiply with 255 here.
Stefan Holmer64be7fa2018-10-04 13:21:55854 encoder_target_rate_bps_ = fec_controller_->UpdateFecRates(
Sebastian Jansson82ed2e82019-10-15 13:58:37855 payload_bitrate_bps, framerate,
856 rtc::saturated_cast<uint8_t>(update.packet_loss_ratio * 256),
857 loss_mask_vector_, update.round_trip_time.ms());
Elad Alon67daf712019-06-28 16:14:36858 if (!fec_allowed_) {
859 encoder_target_rate_bps_ = payload_bitrate_bps;
860 // fec_controller_->UpdateFecRates() was still called so as to allow
Artem Titovea240272021-07-26 10:40:21861 // `fec_controller_` to update whatever internal state it might have,
862 // since `fec_allowed_` may be toggled back on at any moment.
Elad Alon67daf712019-06-28 16:14:36863 }
Erik Språng482b3ef2019-01-08 15:19:11864
Stefan Holmerf5bbb292023-04-28 11:33:42865 // Subtract post encode overhead from the encoder target. If target rate
Artem Titovea240272021-07-26 10:40:21866 // is really low, cap the overhead at 50%. This also avoids the case where
867 // `encoder_target_rate_bps_` is 0 due to encoder pause event while the
868 // packetization rate is positive since packets are still flowing.
Stefan Holmerf5bbb292023-04-28 11:33:42869 uint32_t post_encode_overhead_bps = std::min(
870 GetPostEncodeOverhead().bps<uint32_t>(), encoder_target_rate_bps_ / 2);
871 encoder_target_rate_bps_ -= post_encode_overhead_bps;
Erik Språng482b3ef2019-01-08 15:19:11872
Stefan Holmer64be7fa2018-10-04 13:21:55873 loss_mask_vector_.clear();
874
Sebastian Janssoncf41eb12019-06-10 09:30:59875 uint32_t encoder_overhead_rate_bps = 0;
Per Kjellandere0b4cab2022-11-30 18:41:22876 if (has_packet_feedback_) {
Sebastian Janssoncf41eb12019-06-10 09:30:59877 // TODO(srte): The packet size should probably be the same as in the
878 // CalculateOverheadRate call above (just max_total_packet_size), it doesn't
879 // make sense to use different packet rates for different overhead
880 // calculations.
881 DataRate encoder_overhead_rate = CalculateOverheadRate(
Danil Chapovalovcad3e0e2020-02-17 17:46:07882 DataRate::BitsPerSec(encoder_target_rate_bps_),
Erik Språng04e1bab2020-05-07 16:18:32883 max_total_packet_size - DataSize::Bytes(overhead_bytes_per_packet),
Jakob Ivarsson9a12ee52020-11-26 15:04:18884 packet_overhead, Frequency::Hertz(framerate));
Sebastian Jansson82ed2e82019-10-15 13:58:37885 encoder_overhead_rate_bps = std::min(
886 encoder_overhead_rate.bps<uint32_t>(),
887 update.target_bitrate.bps<uint32_t>() - encoder_target_rate_bps_);
Sebastian Janssoncf41eb12019-06-10 09:30:59888 }
Erik Språngd15687d2019-01-18 09:47:07889 const uint32_t media_rate = encoder_target_rate_bps_ +
890 encoder_overhead_rate_bps +
Stefan Holmerf5bbb292023-04-28 11:33:42891 post_encode_overhead_bps;
Danil Chapovalovcad3e0e2020-02-17 17:46:07892 RTC_DCHECK_GE(update.target_bitrate, DataRate::BitsPerSec(media_rate));
Per Kjellandere0b4cab2022-11-30 18:41:22893 // `protection_bitrate_bps_` includes overhead.
Sebastian Jansson82ed2e82019-10-15 13:58:37894 protection_bitrate_bps_ = update.target_bitrate.bps() - media_rate;
Stefan Holmer64be7fa2018-10-04 13:21:55895}
896
897uint32_t RtpVideoSender::GetPayloadBitrateBps() const {
898 return encoder_target_rate_bps_;
899}
900
901uint32_t RtpVideoSender::GetProtectionBitrateBps() const {
902 return protection_bitrate_bps_;
903}
904
Elad Alon898395d2019-04-10 13:55:00905std::vector<RtpSequenceNumberMap::Info> RtpVideoSender::GetSentRtpPacketInfos(
Elad Alon8b60e8b2019-04-08 12:14:05906 uint32_t ssrc,
Elad Alon898395d2019-04-10 13:55:00907 rtc::ArrayView<const uint16_t> sequence_numbers) const {
Elad Alon8b60e8b2019-04-08 12:14:05908 for (const auto& rtp_stream : rtp_streams_) {
909 if (ssrc == rtp_stream.rtp_rtcp->SSRC()) {
Erik Språng3663f942020-02-07 09:05:15910 return rtp_stream.rtp_rtcp->GetSentRtpPacketInfos(sequence_numbers);
Elad Alon8b60e8b2019-04-08 12:14:05911 }
912 }
Elad Alon898395d2019-04-10 13:55:00913 return std::vector<RtpSequenceNumberMap::Info>();
Elad Alon8b60e8b2019-04-08 12:14:05914}
915
Stefan Holmer64be7fa2018-10-04 13:21:55916int RtpVideoSender::ProtectionRequest(const FecProtectionParams* delta_params,
917 const FecProtectionParams* key_params,
918 uint32_t* sent_video_rate_bps,
919 uint32_t* sent_nack_rate_bps,
920 uint32_t* sent_fec_rate_bps) {
921 *sent_video_rate_bps = 0;
922 *sent_nack_rate_bps = 0;
923 *sent_fec_rate_bps = 0;
Niels Möller5fe95102019-03-04 15:49:25924 for (const RtpStreamSender& stream : rtp_streams_) {
Jared Siskinbceec842023-04-20 21:10:51925 stream.rtp_rtcp->SetFecProtectionParams(*delta_params, *key_params);
Erik Språng1d50cb62020-07-02 15:41:32926
Jared Siskinbceec842023-04-20 21:10:51927 auto send_bitrate = stream.rtp_rtcp->GetSendRates();
928 *sent_video_rate_bps += send_bitrate[RtpPacketMediaType::kVideo].bps();
929 *sent_fec_rate_bps +=
930 send_bitrate[RtpPacketMediaType::kForwardErrorCorrection].bps();
931 *sent_nack_rate_bps +=
932 send_bitrate[RtpPacketMediaType::kRetransmission].bps();
Stefan Holmer64be7fa2018-10-04 13:21:55933 }
934 return 0;
935}
936
Ying Wang2d598532023-06-01 05:55:36937void RtpVideoSender::SetRetransmissionMode(int retransmission_mode) {
938 MutexLock lock(&mutex_);
939 for (const RtpStreamSender& stream : rtp_streams_) {
940 stream.sender_video->SetRetransmissionSetting(retransmission_mode);
941 }
942}
943
Elad Alon8f01c4e2019-06-28 13:19:43944void RtpVideoSender::SetFecAllowed(bool fec_allowed) {
Markus Handell8fe932a2020-07-06 15:41:35945 MutexLock lock(&mutex_);
Elad Alon67daf712019-06-28 16:14:36946 fec_allowed_ = fec_allowed;
Elad Alon8f01c4e2019-06-28 13:19:43947}
948
Stefan Holmer64be7fa2018-10-04 13:21:55949void RtpVideoSender::OnPacketFeedbackVector(
Sebastian Janssonf2988552019-10-29 16:18:51950 std::vector<StreamPacketInfo> packet_feedback_vector) {
Erik Språng490d76c2019-05-07 16:29:15951 if (fec_controller_->UseLossVectorMask()) {
Markus Handell8fe932a2020-07-06 15:41:35952 MutexLock lock(&mutex_);
Sebastian Janssonf2988552019-10-29 16:18:51953 for (const StreamPacketInfo& packet : packet_feedback_vector) {
954 loss_mask_vector_.push_back(!packet.received);
Stefan Holmer64be7fa2018-10-04 13:21:55955 }
956 }
Erik Språng490d76c2019-05-07 16:29:15957
958 // Map from SSRC to all acked packets for that RTP module.
959 std::map<uint32_t, std::vector<uint16_t>> acked_packets_per_ssrc;
Sebastian Janssonf2988552019-10-29 16:18:51960 for (const StreamPacketInfo& packet : packet_feedback_vector) {
Erik Språng6a0a5592021-06-15 17:04:24961 if (packet.received && packet.ssrc) {
962 acked_packets_per_ssrc[*packet.ssrc].push_back(
963 packet.rtp_sequence_number);
Erik Språng490d76c2019-05-07 16:29:15964 }
965 }
966
Erik Språng6a0a5592021-06-15 17:04:24967 // Map from SSRC to vector of RTP sequence numbers that are indicated as
968 // lost by feedback, without being trailed by any received packets.
969 std::map<uint32_t, std::vector<uint16_t>> early_loss_detected_per_ssrc;
Erik Språng845c6aa2019-05-29 11:02:24970
Erik Språng6a0a5592021-06-15 17:04:24971 for (const StreamPacketInfo& packet : packet_feedback_vector) {
972 // Only include new media packets, not retransmissions/padding/fec.
973 if (!packet.received && packet.ssrc && !packet.is_retransmission) {
974 // Last known lost packet, might not be detectable as lost by remote
975 // jitter buffer.
976 early_loss_detected_per_ssrc[*packet.ssrc].push_back(
977 packet.rtp_sequence_number);
978 } else {
979 // Packet received, so any loss prior to this is already detectable.
980 early_loss_detected_per_ssrc.erase(*packet.ssrc);
Erik Språng845c6aa2019-05-29 11:02:24981 }
Erik Språng6a0a5592021-06-15 17:04:24982 }
Erik Språng845c6aa2019-05-29 11:02:24983
Erik Språng6a0a5592021-06-15 17:04:24984 for (const auto& kv : early_loss_detected_per_ssrc) {
985 const uint32_t ssrc = kv.first;
986 auto it = ssrc_to_rtp_module_.find(ssrc);
987 RTC_CHECK(it != ssrc_to_rtp_module_.end());
988 RTPSender* rtp_sender = it->second->RtpSender();
989 for (uint16_t sequence_number : kv.second) {
990 rtp_sender->ReSendPacket(sequence_number);
Erik Språng845c6aa2019-05-29 11:02:24991 }
Erik Språng6a0a5592021-06-15 17:04:24992 }
Erik Språng845c6aa2019-05-29 11:02:24993
Erik Språng490d76c2019-05-07 16:29:15994 for (const auto& kv : acked_packets_per_ssrc) {
995 const uint32_t ssrc = kv.first;
Erik Språnga9229042019-10-24 10:39:32996 auto it = ssrc_to_rtp_module_.find(ssrc);
997 if (it == ssrc_to_rtp_module_.end()) {
Erik Språng6a0a5592021-06-15 17:04:24998 // No media, likely FEC or padding. Ignore since there's no RTP history to
999 // clean up anyway.
Erik Språng490d76c2019-05-07 16:29:151000 continue;
1001 }
1002 rtc::ArrayView<const uint16_t> rtp_sequence_numbers(kv.second);
Erik Språng845c6aa2019-05-29 11:02:241003 it->second->OnPacketsAcknowledged(rtp_sequence_numbers);
Erik Språng490d76c2019-05-07 16:29:151004 }
Stefan Holmer64be7fa2018-10-04 13:21:551005}
1006
1007void RtpVideoSender::SetEncodingData(size_t width,
1008 size_t height,
1009 size_t num_temporal_layers) {
1010 fec_controller_->SetEncodingData(width, height, num_temporal_layers,
1011 rtp_config_.max_packet_size);
1012}
Jakob Ivarsson9a12ee52020-11-26 15:04:181013
1014DataRate RtpVideoSender::CalculateOverheadRate(DataRate data_rate,
1015 DataSize packet_size,
1016 DataSize overhead_per_packet,
1017 Frequency framerate) const {
1018 Frequency packet_rate = data_rate / packet_size;
1019 if (use_frame_rate_for_overhead_) {
1020 framerate = std::max(framerate, Frequency::Hertz(1));
1021 DataSize frame_size = data_rate / framerate;
1022 int packets_per_frame = ceil(frame_size / packet_size);
1023 packet_rate = packets_per_frame * framerate;
1024 }
1025 return packet_rate.RoundUpTo(Frequency::Hertz(1)) * overhead_per_packet;
1026}
1027
mflodman@webrtc.org02270cd2015-02-06 13:10:191028} // namespace webrtc