blob: 214fe96603c9391faea002728d368b063fc0d353 [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
18#include "call/rtp_transport_controller_send_interface.h"
19#include "modules/pacing/packet_router.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3120#include "modules/rtp_rtcp/include/rtp_rtcp.h"
21#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
Stefan Holmerdbdb3a02018-07-17 14:03:4622#include "modules/rtp_rtcp/source/rtp_sender.h"
23#include "modules/utility/include/process_thread.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3124#include "modules/video_coding/include/video_codec_interface.h"
25#include "rtc_base/checks.h"
Stefan Holmerdbdb3a02018-07-17 14:03:4626#include "rtc_base/location.h"
27#include "rtc_base/logging.h"
28#include "system_wrappers/include/field_trial.h"
mflodman@webrtc.org02270cd2015-02-06 13:10:1929
30namespace webrtc {
31
kjellander02b3d272016-04-20 12:05:5432namespace {
Stefan Holmerdbdb3a02018-07-17 14:03:4633static const int kMinSendSidePacketHistorySize = 600;
Stefan Holmer64be7fa2018-10-04 13:21:5534// Assume an average video stream has around 3 packets per frame (1 mbps / 30
35// fps / 1400B) A sequence number set with size 5500 will be able to store
36// packet sequence number for at least last 60 seconds.
37static const int kSendSideSeqNumSetMaxSize = 5500;
38// We don't do MTU discovery, so assume that we have the standard ethernet MTU.
39static const size_t kPathMTU = 1500;
Stefan Holmerdbdb3a02018-07-17 14:03:4640
41std::vector<std::unique_ptr<RtpRtcp>> CreateRtpRtcpModules(
42 const std::vector<uint32_t>& ssrcs,
Johannes Kron9190b822018-10-29 10:22:0543 const RtpConfig& rtp_config,
Stefan Holmerdbdb3a02018-07-17 14:03:4644 const RtcpConfig& rtcp_config,
45 Transport* send_transport,
46 RtcpIntraFrameObserver* intra_frame_callback,
47 RtcpBandwidthObserver* bandwidth_callback,
48 RtpTransportControllerSendInterface* transport,
49 RtcpRttStats* rtt_stats,
50 FlexfecSender* flexfec_sender,
51 BitrateStatisticsObserver* bitrate_observer,
52 FrameCountObserver* frame_count_observer,
53 RtcpPacketTypeCounterObserver* rtcp_type_observer,
54 SendSideDelayObserver* send_delay_observer,
55 SendPacketObserver* send_packet_observer,
56 RtcEventLog* event_log,
57 RateLimiter* retransmission_rate_limiter,
58 OverheadObserver* overhead_observer,
Benjamin Wright192eeec2018-10-18 00:27:2559 RtpKeepAliveConfig keepalive_config,
60 FrameEncryptorInterface* frame_encryptor,
61 const CryptoOptions& crypto_options) {
Stefan Holmerdbdb3a02018-07-17 14:03:4662 RTC_DCHECK_GT(ssrcs.size(), 0);
Benjamin Wright192eeec2018-10-18 00:27:2563
Stefan Holmerdbdb3a02018-07-17 14:03:4664 RtpRtcp::Configuration configuration;
65 configuration.audio = false;
66 configuration.receiver_only = false;
67 configuration.outgoing_transport = send_transport;
68 configuration.intra_frame_callback = intra_frame_callback;
69 configuration.bandwidth_callback = bandwidth_callback;
70 configuration.transport_feedback_callback =
71 transport->transport_feedback_observer();
72 configuration.rtt_stats = rtt_stats;
73 configuration.rtcp_packet_type_counter_observer = rtcp_type_observer;
74 configuration.paced_sender = transport->packet_sender();
75 configuration.transport_sequence_number_allocator =
76 transport->packet_router();
77 configuration.send_bitrate_observer = bitrate_observer;
78 configuration.send_frame_count_observer = frame_count_observer;
79 configuration.send_side_delay_observer = send_delay_observer;
80 configuration.send_packet_observer = send_packet_observer;
81 configuration.event_log = event_log;
82 configuration.retransmission_rate_limiter = retransmission_rate_limiter;
83 configuration.overhead_observer = overhead_observer;
84 configuration.keepalive_config = keepalive_config;
85 configuration.rtcp_interval_config.video_interval_ms =
86 rtcp_config.video_report_interval_ms;
87 configuration.rtcp_interval_config.audio_interval_ms =
88 rtcp_config.audio_report_interval_ms;
Benjamin Wright192eeec2018-10-18 00:27:2589 configuration.frame_encryptor = frame_encryptor;
90 configuration.require_frame_encryption =
91 crypto_options.sframe.require_frame_encryption;
Johannes Kron9190b822018-10-29 10:22:0592 configuration.extmap_allow_mixed = rtp_config.extmap_allow_mixed;
Benjamin Wright192eeec2018-10-18 00:27:2593
Stefan Holmerdbdb3a02018-07-17 14:03:4694 std::vector<std::unique_ptr<RtpRtcp>> modules;
Johannes Kron9190b822018-10-29 10:22:0595 const std::vector<uint32_t>& flexfec_protected_ssrcs =
96 rtp_config.flexfec.protected_media_ssrcs;
Stefan Holmerdbdb3a02018-07-17 14:03:4697 for (uint32_t ssrc : ssrcs) {
98 bool enable_flexfec = flexfec_sender != nullptr &&
99 std::find(flexfec_protected_ssrcs.begin(),
100 flexfec_protected_ssrcs.end(),
101 ssrc) != flexfec_protected_ssrcs.end();
102 configuration.flexfec_sender = enable_flexfec ? flexfec_sender : nullptr;
103 std::unique_ptr<RtpRtcp> rtp_rtcp =
104 std::unique_ptr<RtpRtcp>(RtpRtcp::CreateRtpRtcp(configuration));
105 rtp_rtcp->SetSendingStatus(false);
106 rtp_rtcp->SetSendingMediaStatus(false);
107 rtp_rtcp->SetRTCPStatus(RtcpMode::kCompound);
108 modules.push_back(std::move(rtp_rtcp));
109 }
110 return modules;
111}
112
Stefan Holmerdbdb3a02018-07-17 14:03:46113bool PayloadTypeSupportsSkippingFecPackets(const std::string& payload_name) {
114 const VideoCodecType codecType = PayloadStringToCodecType(payload_name);
115 if (codecType == kVideoCodecVP8 || codecType == kVideoCodecVP9) {
116 return true;
117 }
Sami Kalliomäki22c7d692018-09-03 12:40:05118 if (codecType == kVideoCodecGeneric &&
119 field_trial::IsEnabled("WebRTC-GenericPictureId")) {
120 return true;
121 }
Stefan Holmerdbdb3a02018-07-17 14:03:46122 return false;
123}
124
125// TODO(brandtr): Update this function when we support multistream protection.
126std::unique_ptr<FlexfecSender> MaybeCreateFlexfecSender(
127 const RtpConfig& rtp,
128 const std::map<uint32_t, RtpState>& suspended_ssrcs) {
129 if (rtp.flexfec.payload_type < 0) {
130 return nullptr;
131 }
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 const RtpState* rtp_state = nullptr;
156 auto it = suspended_ssrcs.find(rtp.flexfec.ssrc);
157 if (it != suspended_ssrcs.end()) {
158 rtp_state = &it->second;
159 }
160
161 RTC_DCHECK_EQ(1U, rtp.flexfec.protected_media_ssrcs.size());
162 return absl::make_unique<FlexfecSender>(
163 rtp.flexfec.payload_type, rtp.flexfec.ssrc,
164 rtp.flexfec.protected_media_ssrcs[0], rtp.mid, rtp.extensions,
165 RTPSender::FecExtensionSizes(), rtp_state, Clock::GetRealTimeClock());
166}
Stefan Holmer64be7fa2018-10-04 13:21:55167
168uint32_t CalculateOverheadRateBps(int packets_per_second,
169 size_t overhead_bytes_per_packet,
170 uint32_t max_overhead_bps) {
171 uint32_t overhead_bps =
172 static_cast<uint32_t>(8 * overhead_bytes_per_packet * packets_per_second);
173 return std::min(overhead_bps, max_overhead_bps);
174}
175
176int CalculatePacketRate(uint32_t bitrate_bps, size_t packet_size_bytes) {
177 size_t packet_size_bits = 8 * packet_size_bytes;
178 // Ceil for int value of bitrate_bps / packet_size_bits.
179 return static_cast<int>((bitrate_bps + packet_size_bits - 1) /
180 packet_size_bits);
181}
kjellander02b3d272016-04-20 12:05:54182} // namespace
183
Stefan Holmer9416ef82018-07-19 08:34:38184RtpVideoSender::RtpVideoSender(
185 const std::vector<uint32_t>& ssrcs,
186 std::map<uint32_t, RtpState> suspended_ssrcs,
187 const std::map<uint32_t, RtpPayloadState>& states,
188 const RtpConfig& rtp_config,
189 const RtcpConfig& rtcp_config,
190 Transport* send_transport,
191 const RtpSenderObservers& observers,
192 RtpTransportControllerSendInterface* transport,
193 RtcEventLog* event_log,
Stefan Holmer64be7fa2018-10-04 13:21:55194 RateLimiter* retransmission_limiter,
Benjamin Wright192eeec2018-10-18 00:27:25195 std::unique_ptr<FecController> fec_controller,
196 FrameEncryptorInterface* frame_encryptor,
197 const CryptoOptions& crypto_options)
Stefan Holmer64be7fa2018-10-04 13:21:55198 : send_side_bwe_with_overhead_(
199 webrtc::field_trial::IsEnabled("WebRTC-SendSideBwe-WithOverhead")),
200 active_(false),
Stefan Holmerdbdb3a02018-07-17 14:03:46201 module_process_thread_(nullptr),
202 suspended_ssrcs_(std::move(suspended_ssrcs)),
203 flexfec_sender_(MaybeCreateFlexfecSender(rtp_config, suspended_ssrcs_)),
Stefan Holmer64be7fa2018-10-04 13:21:55204 fec_controller_(std::move(fec_controller)),
Johannes Kron9190b822018-10-29 10:22:05205 rtp_modules_(CreateRtpRtcpModules(ssrcs,
206 rtp_config,
207 rtcp_config,
208 send_transport,
209 observers.intra_frame_callback,
210 transport->GetBandwidthObserver(),
211 transport,
212 observers.rtcp_rtt_stats,
213 flexfec_sender_.get(),
214 observers.bitrate_observer,
215 observers.frame_count_observer,
216 observers.rtcp_type_observer,
217 observers.send_delay_observer,
218 observers.send_packet_observer,
219 event_log,
220 retransmission_limiter,
221 this,
222 transport->keepalive_config(),
223 frame_encryptor,
224 crypto_options)),
Stefan Holmerdbdb3a02018-07-17 14:03:46225 rtp_config_(rtp_config),
Stefan Holmer64be7fa2018-10-04 13:21:55226 transport_(transport),
227 transport_overhead_bytes_per_packet_(0),
228 overhead_bytes_per_packet_(0),
229 encoder_target_rate_bps_(0) {
Stefan Holmerdbdb3a02018-07-17 14:03:46230 RTC_DCHECK_EQ(ssrcs.size(), rtp_modules_.size());
231 module_process_thread_checker_.DetachFromThread();
Ã…sa Persson4bece9a2017-10-06 08:04:04232 // SSRCs are assumed to be sorted in the same order as |rtp_modules|.
233 for (uint32_t ssrc : ssrcs) {
234 // Restore state if it previously existed.
235 const RtpPayloadState* state = nullptr;
236 auto it = states.find(ssrc);
237 if (it != states.end()) {
238 state = &it->second;
philipel25d31ec2018-08-08 14:33:01239 shared_frame_id_ = std::max(shared_frame_id_, state->shared_frame_id);
Ã…sa Persson4bece9a2017-10-06 08:04:04240 }
241 params_.push_back(RtpPayloadParams(ssrc, state));
242 }
Stefan Holmerdbdb3a02018-07-17 14:03:46243
244 // RTP/RTCP initialization.
245
246 // We add the highest spatial layer first to ensure it'll be prioritized
247 // when sending padding, with the hope that the packet rate will be smaller,
248 // and that it's more important to protect than the lower layers.
Niels Möller2ff1f2a2018-08-09 14:16:34249
250 // TODO(nisse): Consider moving registration with PacketRouter last, after the
251 // modules are fully configured.
Stefan Holmerdbdb3a02018-07-17 14:03:46252 for (auto& rtp_rtcp : rtp_modules_) {
253 constexpr bool remb_candidate = true;
254 transport->packet_router()->AddSendRtpModule(rtp_rtcp.get(),
255 remb_candidate);
256 }
257
258 for (size_t i = 0; i < rtp_config_.extensions.size(); ++i) {
259 const std::string& extension = rtp_config_.extensions[i].uri;
260 int id = rtp_config_.extensions[i].id;
Stefan Holmerdbdb3a02018-07-17 14:03:46261 RTC_DCHECK(RtpExtension::IsSupportedForVideo(extension));
262 for (auto& rtp_rtcp : rtp_modules_) {
Danil Chapovalov585d1aa2018-09-14 16:29:32263 RTC_CHECK(rtp_rtcp->RegisterRtpHeaderExtension(extension, id));
Stefan Holmerdbdb3a02018-07-17 14:03:46264 }
265 }
266
267 ConfigureProtection(rtp_config);
268 ConfigureSsrcs(rtp_config);
269
270 if (!rtp_config.mid.empty()) {
271 for (auto& rtp_rtcp : rtp_modules_) {
272 rtp_rtcp->SetMid(rtp_config.mid);
273 }
274 }
275
276 // TODO(pbos): Should we set CNAME on all RTP modules?
277 rtp_modules_.front()->SetCNAME(rtp_config.c_name.c_str());
278
279 for (auto& rtp_rtcp : rtp_modules_) {
280 rtp_rtcp->RegisterRtcpStatisticsCallback(observers.rtcp_stats);
281 rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(observers.rtp_stats);
282 rtp_rtcp->SetMaxRtpPacketSize(rtp_config.max_packet_size);
283 rtp_rtcp->RegisterVideoSendPayload(rtp_config.payload_type,
284 rtp_config.payload_name.c_str());
285 }
Stefan Holmer64be7fa2018-10-04 13:21:55286 // Currently, both ULPFEC and FlexFEC use the same FEC rate calculation logic,
287 // so enable that logic if either of those FEC schemes are enabled.
288 fec_controller_->SetProtectionMethod(FecEnabled(), NackEnabled());
289
290 fec_controller_->SetProtectionCallback(this);
291 // Signal congestion controller this object is ready for OnPacket* callbacks.
292 if (fec_controller_->UseLossVectorMask()) {
293 transport_->RegisterPacketFeedbackObserver(this);
294 }
Per83d09102016-04-15 12:59:13295}
mflodman@webrtc.org02270cd2015-02-06 13:10:19296
Stefan Holmer9416ef82018-07-19 08:34:38297RtpVideoSender::~RtpVideoSender() {
Stefan Holmerdbdb3a02018-07-17 14:03:46298 for (auto& rtp_rtcp : rtp_modules_) {
299 transport_->packet_router()->RemoveSendRtpModule(rtp_rtcp.get());
300 }
Stefan Holmer64be7fa2018-10-04 13:21:55301 if (fec_controller_->UseLossVectorMask()) {
302 transport_->DeRegisterPacketFeedbackObserver(this);
303 }
Stefan Holmerdbdb3a02018-07-17 14:03:46304}
305
Stefan Holmer9416ef82018-07-19 08:34:38306void RtpVideoSender::RegisterProcessThread(
Stefan Holmerdbdb3a02018-07-17 14:03:46307 ProcessThread* module_process_thread) {
308 RTC_DCHECK_RUN_ON(&module_process_thread_checker_);
309 RTC_DCHECK(!module_process_thread_);
310 module_process_thread_ = module_process_thread;
311
312 for (auto& rtp_rtcp : rtp_modules_)
313 module_process_thread_->RegisterModule(rtp_rtcp.get(), RTC_FROM_HERE);
314}
315
Stefan Holmer9416ef82018-07-19 08:34:38316void RtpVideoSender::DeRegisterProcessThread() {
Stefan Holmerdbdb3a02018-07-17 14:03:46317 RTC_DCHECK_RUN_ON(&module_process_thread_checker_);
318 for (auto& rtp_rtcp : rtp_modules_)
319 module_process_thread_->DeRegisterModule(rtp_rtcp.get());
320}
mflodman@webrtc.org02270cd2015-02-06 13:10:19321
Stefan Holmer9416ef82018-07-19 08:34:38322void RtpVideoSender::SetActive(bool active) {
Tommi97888bd2016-01-21 22:24:59323 rtc::CritScope lock(&crit_);
Peter Boström8b79b072016-02-26 15:31:37324 if (active_ == active)
325 return;
Seth Hampsoncc7125f2018-02-02 16:46:16326 const std::vector<bool> active_modules(rtp_modules_.size(), active);
327 SetActiveModules(active_modules);
328}
Per512ecb32016-09-23 13:52:06329
Stefan Holmer9416ef82018-07-19 08:34:38330void RtpVideoSender::SetActiveModules(const std::vector<bool> active_modules) {
Seth Hampsoncc7125f2018-02-02 16:46:16331 rtc::CritScope lock(&crit_);
332 RTC_DCHECK_EQ(rtp_modules_.size(), active_modules.size());
333 active_ = false;
334 for (size_t i = 0; i < active_modules.size(); ++i) {
335 if (active_modules[i]) {
336 active_ = true;
337 }
338 // Sends a kRtcpByeCode when going from true to false.
339 rtp_modules_[i]->SetSendingStatus(active_modules[i]);
340 // If set to false this module won't send media.
341 rtp_modules_[i]->SetSendingMediaStatus(active_modules[i]);
Per512ecb32016-09-23 13:52:06342 }
mflodman@webrtc.org02270cd2015-02-06 13:10:19343}
344
Stefan Holmer9416ef82018-07-19 08:34:38345bool RtpVideoSender::IsActive() {
Tommi97888bd2016-01-21 22:24:59346 rtc::CritScope lock(&crit_);
mflodman@webrtc.org47d657b2015-02-19 10:29:32347 return active_ && !rtp_modules_.empty();
mflodman@webrtc.org02270cd2015-02-06 13:10:19348}
349
Stefan Holmer9416ef82018-07-19 08:34:38350EncodedImageCallback::Result RtpVideoSender::OnEncodedImage(
Sergey Ulanov525df3f2016-08-03 00:46:41351 const EncodedImage& encoded_image,
352 const CodecSpecificInfo* codec_specific_info,
353 const RTPFragmentationHeader* fragmentation) {
Stefan Holmer64be7fa2018-10-04 13:21:55354 fec_controller_->UpdateWithEncodedData(encoded_image._length,
355 encoded_image._frameType);
Tommi97888bd2016-01-21 22:24:59356 rtc::CritScope lock(&crit_);
Peter Boström8b79b072016-02-26 15:31:37357 RTC_DCHECK(!rtp_modules_.empty());
Per512ecb32016-09-23 13:52:06358 if (!active_)
Sergey Ulanov525df3f2016-08-03 00:46:41359 return Result(Result::ERROR_SEND_FAILED);
mflodman@webrtc.org50e28162015-02-23 07:45:11360
philipelbf2b6202018-08-27 12:33:18361 shared_frame_id_++;
Niels Möllerd3b8c632018-08-27 13:33:42362 size_t stream_index = 0;
363 if (codec_specific_info &&
364 (codec_specific_info->codecType == kVideoCodecVP8 ||
365 codec_specific_info->codecType == kVideoCodecH264 ||
366 codec_specific_info->codecType == kVideoCodecGeneric)) {
367 // Map spatial index to simulcast.
368 stream_index = encoded_image.SpatialIndex().value_or(0);
369 }
sergeyu7b9feee2016-11-18 00:16:14370 RTC_DCHECK_LT(stream_index, rtp_modules_.size());
Stefan Holmerf7044682018-07-17 08:16:41371 RTPVideoHeader rtp_video_header = params_[stream_index].GetRtpVideoHeader(
philipelbf2b6202018-08-27 12:33:18372 encoded_image, codec_specific_info, shared_frame_id_);
Niels Möllerbb894ff2018-03-15 11:28:53373
Sergey Ulanov525df3f2016-08-03 00:46:41374 uint32_t frame_id;
Seth Hampsoncc7125f2018-02-02 16:46:16375 if (!rtp_modules_[stream_index]->Sending()) {
376 // The payload router could be active but this module isn't sending.
377 return Result(Result::ERROR_SEND_FAILED);
378 }
sergeyu7b9feee2016-11-18 00:16:14379 bool send_result = rtp_modules_[stream_index]->SendOutgoingData(
Stefan Holmerdbdb3a02018-07-17 14:03:46380 encoded_image._frameType, rtp_config_.payload_type,
Niels Möller23775882018-08-16 08:24:12381 encoded_image.Timestamp(), encoded_image.capture_time_ms_,
Stefan Holmerdbdb3a02018-07-17 14:03:46382 encoded_image._buffer, encoded_image._length, fragmentation,
383 &rtp_video_header, &frame_id);
sergeyu7b9feee2016-11-18 00:16:14384 if (!send_result)
Sergey Ulanov525df3f2016-08-03 00:46:41385 return Result(Result::ERROR_SEND_FAILED);
386
387 return Result(Result::OK, frame_id);
mflodman@webrtc.orga4ef2ce2015-02-12 09:54:18388}
389
Stefan Holmer9416ef82018-07-19 08:34:38390void RtpVideoSender::OnBitrateAllocationUpdated(
Erik Språng566124a2018-04-23 10:32:22391 const VideoBitrateAllocation& bitrate) {
sprang1a646ee2016-12-01 14:34:11392 rtc::CritScope lock(&crit_);
393 if (IsActive()) {
394 if (rtp_modules_.size() == 1) {
395 // If spatial scalability is enabled, it is covered by a single stream.
396 rtp_modules_[0]->SetVideoBitrateAllocation(bitrate);
397 } else {
Stefan Holmerf7044682018-07-17 08:16:41398 std::vector<absl::optional<VideoBitrateAllocation>> layer_bitrates =
399 bitrate.GetSimulcastAllocations();
Erik Språng566124a2018-04-23 10:32:22400 // Simulcast is in use, split the VideoBitrateAllocation into one struct
401 // per rtp stream, moving over the temporal layer allocation.
Stefan Holmerf7044682018-07-17 08:16:41402 for (size_t i = 0; i < rtp_modules_.size(); ++i) {
403 // The next spatial layer could be used if the current one is
404 // inactive.
405 if (layer_bitrates[i]) {
406 rtp_modules_[i]->SetVideoBitrateAllocation(*layer_bitrates[i]);
Ilya Nikolaevskiyb0588e62018-08-27 12:12:27407 } else {
408 // Signal a 0 bitrate on a simulcast stream.
409 rtp_modules_[i]->SetVideoBitrateAllocation(VideoBitrateAllocation());
Seth Hampson46e31ba2018-01-18 18:39:54410 }
sprang1a646ee2016-12-01 14:34:11411 }
412 }
413 }
414}
415
Stefan Holmer9416ef82018-07-19 08:34:38416void RtpVideoSender::ConfigureProtection(const RtpConfig& rtp_config) {
Stefan Holmerdbdb3a02018-07-17 14:03:46417 // Consistency of FlexFEC parameters is checked in MaybeCreateFlexfecSender.
418 const bool flexfec_enabled = (flexfec_sender_ != nullptr);
419
420 // Consistency of NACK and RED+ULPFEC parameters is checked in this function.
421 const bool nack_enabled = rtp_config.nack.rtp_history_ms > 0;
422 int red_payload_type = rtp_config.ulpfec.red_payload_type;
423 int ulpfec_payload_type = rtp_config.ulpfec.ulpfec_payload_type;
424
425 // Shorthands.
426 auto IsRedEnabled = [&]() { return red_payload_type >= 0; };
427 auto IsUlpfecEnabled = [&]() { return ulpfec_payload_type >= 0; };
428 auto DisableRedAndUlpfec = [&]() {
429 red_payload_type = -1;
430 ulpfec_payload_type = -1;
431 };
432
433 if (webrtc::field_trial::IsEnabled("WebRTC-DisableUlpFecExperiment")) {
434 RTC_LOG(LS_INFO) << "Experiment to disable sending ULPFEC is enabled.";
435 DisableRedAndUlpfec();
436 }
437
438 // If enabled, FlexFEC takes priority over RED+ULPFEC.
439 if (flexfec_enabled) {
440 if (IsUlpfecEnabled()) {
441 RTC_LOG(LS_INFO)
442 << "Both FlexFEC and ULPFEC are configured. Disabling ULPFEC.";
443 }
444 DisableRedAndUlpfec();
445 }
446
447 // Payload types without picture ID cannot determine that a stream is complete
448 // without retransmitting FEC, so using ULPFEC + NACK for H.264 (for instance)
449 // is a waste of bandwidth since FEC packets still have to be transmitted.
450 // Note that this is not the case with FlexFEC.
451 if (nack_enabled && IsUlpfecEnabled() &&
452 !PayloadTypeSupportsSkippingFecPackets(rtp_config.payload_name)) {
453 RTC_LOG(LS_WARNING)
454 << "Transmitting payload type without picture ID using "
455 "NACK+ULPFEC is a waste of bandwidth since ULPFEC packets "
456 "also have to be retransmitted. Disabling ULPFEC.";
457 DisableRedAndUlpfec();
458 }
459
460 // Verify payload types.
461 if (IsUlpfecEnabled() ^ IsRedEnabled()) {
462 RTC_LOG(LS_WARNING)
463 << "Only RED or only ULPFEC enabled, but not both. Disabling both.";
464 DisableRedAndUlpfec();
465 }
466
467 for (auto& rtp_rtcp : rtp_modules_) {
468 // Set NACK.
469 rtp_rtcp->SetStorePacketsStatus(true, kMinSendSidePacketHistorySize);
470 // Set RED/ULPFEC information.
471 rtp_rtcp->SetUlpfecConfig(red_payload_type, ulpfec_payload_type);
472 }
473}
474
Stefan Holmer9416ef82018-07-19 08:34:38475bool RtpVideoSender::FecEnabled() const {
Stefan Holmerdbdb3a02018-07-17 14:03:46476 const bool flexfec_enabled = (flexfec_sender_ != nullptr);
Emircan Uysalera7af0212018-09-22 23:11:29477 const bool ulpfec_enabled =
478 !webrtc::field_trial::IsEnabled("WebRTC-DisableUlpFecExperiment") &&
479 (rtp_config_.ulpfec.ulpfec_payload_type >= 0);
480 return flexfec_enabled || ulpfec_enabled;
Stefan Holmerdbdb3a02018-07-17 14:03:46481}
482
Stefan Holmer9416ef82018-07-19 08:34:38483bool RtpVideoSender::NackEnabled() const {
Stefan Holmerdbdb3a02018-07-17 14:03:46484 const bool nack_enabled = rtp_config_.nack.rtp_history_ms > 0;
485 return nack_enabled;
486}
487
Stefan Holmer9416ef82018-07-19 08:34:38488void RtpVideoSender::DeliverRtcp(const uint8_t* packet, size_t length) {
Stefan Holmerdbdb3a02018-07-17 14:03:46489 // Runs on a network thread.
490 for (auto& rtp_rtcp : rtp_modules_)
491 rtp_rtcp->IncomingRtcpPacket(packet, length);
492}
493
Stefan Holmer9416ef82018-07-19 08:34:38494void RtpVideoSender::ConfigureSsrcs(const RtpConfig& rtp_config) {
Stefan Holmerdbdb3a02018-07-17 14:03:46495 // Configure regular SSRCs.
496 for (size_t i = 0; i < rtp_config.ssrcs.size(); ++i) {
497 uint32_t ssrc = rtp_config.ssrcs[i];
498 RtpRtcp* const rtp_rtcp = rtp_modules_[i].get();
499 rtp_rtcp->SetSSRC(ssrc);
500
501 // Restore RTP state if previous existed.
502 auto it = suspended_ssrcs_.find(ssrc);
503 if (it != suspended_ssrcs_.end())
504 rtp_rtcp->SetRtpState(it->second);
505 }
506
507 // Set up RTX if available.
508 if (rtp_config.rtx.ssrcs.empty())
509 return;
510
511 // Configure RTX SSRCs.
512 RTC_DCHECK_EQ(rtp_config.rtx.ssrcs.size(), rtp_config.ssrcs.size());
513 for (size_t i = 0; i < rtp_config.rtx.ssrcs.size(); ++i) {
514 uint32_t ssrc = rtp_config.rtx.ssrcs[i];
515 RtpRtcp* const rtp_rtcp = rtp_modules_[i].get();
516 rtp_rtcp->SetRtxSsrc(ssrc);
517 auto it = suspended_ssrcs_.find(ssrc);
518 if (it != suspended_ssrcs_.end())
519 rtp_rtcp->SetRtxState(it->second);
520 }
521
522 // Configure RTX payload types.
523 RTC_DCHECK_GE(rtp_config.rtx.payload_type, 0);
524 for (auto& rtp_rtcp : rtp_modules_) {
525 rtp_rtcp->SetRtxSendPayloadType(rtp_config.rtx.payload_type,
526 rtp_config.payload_type);
527 rtp_rtcp->SetRtxSendStatus(kRtxRetransmitted | kRtxRedundantPayloads);
528 }
529 if (rtp_config.ulpfec.red_payload_type != -1 &&
530 rtp_config.ulpfec.red_rtx_payload_type != -1) {
531 for (auto& rtp_rtcp : rtp_modules_) {
532 rtp_rtcp->SetRtxSendPayloadType(rtp_config.ulpfec.red_rtx_payload_type,
533 rtp_config.ulpfec.red_payload_type);
534 }
535 }
536}
537
Stefan Holmer9416ef82018-07-19 08:34:38538void RtpVideoSender::OnNetworkAvailability(bool network_available) {
Stefan Holmerdbdb3a02018-07-17 14:03:46539 for (auto& rtp_rtcp : rtp_modules_) {
540 rtp_rtcp->SetRTCPStatus(network_available ? rtp_config_.rtcp_mode
541 : RtcpMode::kOff);
542 }
543}
544
Stefan Holmer9416ef82018-07-19 08:34:38545std::map<uint32_t, RtpState> RtpVideoSender::GetRtpStates() const {
Stefan Holmerdbdb3a02018-07-17 14:03:46546 std::map<uint32_t, RtpState> rtp_states;
547
548 for (size_t i = 0; i < rtp_config_.ssrcs.size(); ++i) {
549 uint32_t ssrc = rtp_config_.ssrcs[i];
550 RTC_DCHECK_EQ(ssrc, rtp_modules_[i]->SSRC());
551 rtp_states[ssrc] = rtp_modules_[i]->GetRtpState();
552 }
553
554 for (size_t i = 0; i < rtp_config_.rtx.ssrcs.size(); ++i) {
555 uint32_t ssrc = rtp_config_.rtx.ssrcs[i];
556 rtp_states[ssrc] = rtp_modules_[i]->GetRtxState();
557 }
558
559 if (flexfec_sender_) {
560 uint32_t ssrc = rtp_config_.flexfec.ssrc;
561 rtp_states[ssrc] = flexfec_sender_->GetRtpState();
562 }
563
564 return rtp_states;
565}
566
Stefan Holmer9416ef82018-07-19 08:34:38567std::map<uint32_t, RtpPayloadState> RtpVideoSender::GetRtpPayloadStates()
568 const {
Stefan Holmerdbdb3a02018-07-17 14:03:46569 rtc::CritScope lock(&crit_);
570 std::map<uint32_t, RtpPayloadState> payload_states;
571 for (const auto& param : params_) {
572 payload_states[param.ssrc()] = param.state();
philipel25d31ec2018-08-08 14:33:01573 payload_states[param.ssrc()].shared_frame_id = shared_frame_id_;
Stefan Holmerdbdb3a02018-07-17 14:03:46574 }
575 return payload_states;
576}
Stefan Holmer64be7fa2018-10-04 13:21:55577
578void RtpVideoSender::OnTransportOverheadChanged(
579 size_t transport_overhead_bytes_per_packet) {
580 rtc::CritScope lock(&crit_);
581 transport_overhead_bytes_per_packet_ = transport_overhead_bytes_per_packet;
582
583 size_t max_rtp_packet_size =
584 std::min(rtp_config_.max_packet_size,
585 kPathMTU - transport_overhead_bytes_per_packet_);
586 for (auto& rtp_rtcp : rtp_modules_) {
587 rtp_rtcp->SetMaxRtpPacketSize(max_rtp_packet_size);
588 }
589}
590
591void RtpVideoSender::OnOverheadChanged(size_t overhead_bytes_per_packet) {
592 rtc::CritScope lock(&crit_);
593 overhead_bytes_per_packet_ = overhead_bytes_per_packet;
594}
595
596void RtpVideoSender::OnBitrateUpdated(uint32_t bitrate_bps,
597 uint8_t fraction_loss,
598 int64_t rtt,
599 int framerate) {
600 // Substract overhead from bitrate.
601 rtc::CritScope lock(&crit_);
602 uint32_t payload_bitrate_bps = bitrate_bps;
603 if (send_side_bwe_with_overhead_) {
Bjorn Terelius25068392018-10-25 09:07:29604 uint32_t overhead_bps = CalculateOverheadRateBps(
Stefan Holmer64be7fa2018-10-04 13:21:55605 CalculatePacketRate(
606 bitrate_bps,
607 rtp_config_.max_packet_size + transport_overhead_bytes_per_packet_),
608 overhead_bytes_per_packet_ + transport_overhead_bytes_per_packet_,
609 bitrate_bps);
Bjorn Terelius25068392018-10-25 09:07:29610 RTC_DCHECK_LE(overhead_bps, bitrate_bps);
611 payload_bitrate_bps = bitrate_bps - overhead_bps;
Stefan Holmer64be7fa2018-10-04 13:21:55612 }
613
614 // Get the encoder target rate. It is the estimated network rate -
615 // protection overhead.
616 encoder_target_rate_bps_ = fec_controller_->UpdateFecRates(
617 payload_bitrate_bps, framerate, fraction_loss, loss_mask_vector_, rtt);
618 loss_mask_vector_.clear();
619
620 uint32_t encoder_overhead_rate_bps =
621 send_side_bwe_with_overhead_
622 ? CalculateOverheadRateBps(
623 CalculatePacketRate(encoder_target_rate_bps_,
624 rtp_config_.max_packet_size +
625 transport_overhead_bytes_per_packet_ -
626 overhead_bytes_per_packet_),
627 overhead_bytes_per_packet_ +
628 transport_overhead_bytes_per_packet_,
629 bitrate_bps - encoder_target_rate_bps_)
630 : 0;
631
632 // When the field trial "WebRTC-SendSideBwe-WithOverhead" is enabled
633 // protection_bitrate includes overhead.
634 protection_bitrate_bps_ =
635 bitrate_bps - (encoder_target_rate_bps_ + encoder_overhead_rate_bps);
636}
637
638uint32_t RtpVideoSender::GetPayloadBitrateBps() const {
639 return encoder_target_rate_bps_;
640}
641
642uint32_t RtpVideoSender::GetProtectionBitrateBps() const {
643 return protection_bitrate_bps_;
644}
645
646int RtpVideoSender::ProtectionRequest(const FecProtectionParams* delta_params,
647 const FecProtectionParams* key_params,
648 uint32_t* sent_video_rate_bps,
649 uint32_t* sent_nack_rate_bps,
650 uint32_t* sent_fec_rate_bps) {
651 *sent_video_rate_bps = 0;
652 *sent_nack_rate_bps = 0;
653 *sent_fec_rate_bps = 0;
654 for (auto& rtp_rtcp : rtp_modules_) {
655 uint32_t not_used = 0;
656 uint32_t module_video_rate = 0;
657 uint32_t module_fec_rate = 0;
658 uint32_t module_nack_rate = 0;
659 rtp_rtcp->SetFecParameters(*delta_params, *key_params);
660 rtp_rtcp->BitrateSent(&not_used, &module_video_rate, &module_fec_rate,
661 &module_nack_rate);
662 *sent_video_rate_bps += module_video_rate;
663 *sent_nack_rate_bps += module_nack_rate;
664 *sent_fec_rate_bps += module_fec_rate;
665 }
666 return 0;
667}
668
669void RtpVideoSender::OnPacketAdded(uint32_t ssrc, uint16_t seq_num) {
670 const auto ssrcs = rtp_config_.ssrcs;
671 if (std::find(ssrcs.begin(), ssrcs.end(), ssrc) != ssrcs.end()) {
672 feedback_packet_seq_num_set_.insert(seq_num);
673 if (feedback_packet_seq_num_set_.size() > kSendSideSeqNumSetMaxSize) {
674 RTC_LOG(LS_WARNING) << "Feedback packet sequence number set exceed it's "
675 "max size', will get reset.";
676 feedback_packet_seq_num_set_.clear();
677 }
678 }
679}
680
681void RtpVideoSender::OnPacketFeedbackVector(
682 const std::vector<PacketFeedback>& packet_feedback_vector) {
683 rtc::CritScope lock(&crit_);
684 // Lost feedbacks are not considered to be lost packets.
685 for (const PacketFeedback& packet : packet_feedback_vector) {
686 auto it = feedback_packet_seq_num_set_.find(packet.sequence_number);
687 if (it != feedback_packet_seq_num_set_.end()) {
688 const bool lost = packet.arrival_time_ms == PacketFeedback::kNotReceived;
689 loss_mask_vector_.push_back(lost);
690 feedback_packet_seq_num_set_.erase(it);
691 }
692 }
693}
694
695void RtpVideoSender::SetEncodingData(size_t width,
696 size_t height,
697 size_t num_temporal_layers) {
698 fec_controller_->SetEncodingData(width, height, num_temporal_layers,
699 rtp_config_.max_packet_size);
700}
mflodman@webrtc.org02270cd2015-02-06 13:10:19701} // namespace webrtc