blob: 9958d36e5eb5745997772647c9d77d8d7a1d6dce [file] [log] [blame]
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +00001/*
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 10:34:38 +020011#include "call/rtp_video_sender.h"
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +000012
philipel25d31ec2018-08-08 16:33:01 +020013#include <algorithm>
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020014#include <memory>
15#include <string>
16#include <utility>
17
Steve Anton40d55332019-01-07 10:21:47 -080018#include "absl/memory/memory.h"
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020019#include "call/rtp_transport_controller_send_interface.h"
20#include "modules/pacing/packet_router.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020021#include "modules/rtp_rtcp/include/rtp_rtcp.h"
22#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020023#include "modules/rtp_rtcp/source/rtp_sender.h"
24#include "modules/utility/include/process_thread.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020025#include "modules/video_coding/include/video_codec_interface.h"
26#include "rtc_base/checks.h"
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020027#include "rtc_base/location.h"
28#include "rtc_base/logging.h"
29#include "system_wrappers/include/field_trial.h"
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +000030
31namespace webrtc {
32
kjellander02b3d272016-04-20 05:05:54 -070033namespace {
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020034static const int kMinSendSidePacketHistorySize = 600;
Stefan Holmer64be7fa2018-10-04 15:21:55 +020035// Assume an average video stream has around 3 packets per frame (1 mbps / 30
36// fps / 1400B) A sequence number set with size 5500 will be able to store
37// packet sequence number for at least last 60 seconds.
38static const int kSendSideSeqNumSetMaxSize = 5500;
39// We don't do MTU discovery, so assume that we have the standard ethernet MTU.
40static const size_t kPathMTU = 1500;
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020041
42std::vector<std::unique_ptr<RtpRtcp>> CreateRtpRtcpModules(
Johannes Kron9190b822018-10-29 11:22:05 +010043 const RtpConfig& rtp_config,
Jiawei Ou55718122018-11-09 13:17:39 -080044 int rtcp_report_interval_ms,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020045 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-17 17:27:25 -070059 RtpKeepAliveConfig keepalive_config,
60 FrameEncryptorInterface* frame_encryptor,
61 const CryptoOptions& crypto_options) {
Amit Hilbuch0fc28432018-12-18 13:01:47 -080062 RTC_DCHECK_GT(rtp_config.ssrcs.size(), 0);
Benjamin Wright192eeec2018-10-17 17:27:25 -070063
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020064 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;
Benjamin Wright192eeec2018-10-17 17:27:25 -070085 configuration.frame_encryptor = frame_encryptor;
86 configuration.require_frame_encryption =
87 crypto_options.sframe.require_frame_encryption;
Johannes Kron9190b822018-10-29 11:22:05 +010088 configuration.extmap_allow_mixed = rtp_config.extmap_allow_mixed;
Jiawei Ou8b5d9d82018-11-15 16:44:37 -080089 configuration.rtcp_report_interval_ms = rtcp_report_interval_ms;
Benjamin Wright192eeec2018-10-17 17:27:25 -070090
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020091 std::vector<std::unique_ptr<RtpRtcp>> modules;
Johannes Kron9190b822018-10-29 11:22:05 +010092 const std::vector<uint32_t>& flexfec_protected_ssrcs =
93 rtp_config.flexfec.protected_media_ssrcs;
Amit Hilbuch0fc28432018-12-18 13:01:47 -080094 for (uint32_t ssrc : rtp_config.ssrcs) {
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020095 bool enable_flexfec = flexfec_sender != nullptr &&
96 std::find(flexfec_protected_ssrcs.begin(),
97 flexfec_protected_ssrcs.end(),
98 ssrc) != flexfec_protected_ssrcs.end();
99 configuration.flexfec_sender = enable_flexfec ? flexfec_sender : nullptr;
100 std::unique_ptr<RtpRtcp> rtp_rtcp =
101 std::unique_ptr<RtpRtcp>(RtpRtcp::CreateRtpRtcp(configuration));
102 rtp_rtcp->SetSendingStatus(false);
103 rtp_rtcp->SetSendingMediaStatus(false);
104 rtp_rtcp->SetRTCPStatus(RtcpMode::kCompound);
105 modules.push_back(std::move(rtp_rtcp));
106 }
107 return modules;
108}
109
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200110bool PayloadTypeSupportsSkippingFecPackets(const std::string& payload_name) {
111 const VideoCodecType codecType = PayloadStringToCodecType(payload_name);
112 if (codecType == kVideoCodecVP8 || codecType == kVideoCodecVP9) {
113 return true;
114 }
Sami Kalliomäki22c7d692018-09-03 14:40:05 +0200115 if (codecType == kVideoCodecGeneric &&
116 field_trial::IsEnabled("WebRTC-GenericPictureId")) {
117 return true;
118 }
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200119 return false;
120}
121
122// TODO(brandtr): Update this function when we support multistream protection.
123std::unique_ptr<FlexfecSender> MaybeCreateFlexfecSender(
124 const RtpConfig& rtp,
125 const std::map<uint32_t, RtpState>& suspended_ssrcs) {
126 if (rtp.flexfec.payload_type < 0) {
127 return nullptr;
128 }
129 RTC_DCHECK_GE(rtp.flexfec.payload_type, 0);
130 RTC_DCHECK_LE(rtp.flexfec.payload_type, 127);
131 if (rtp.flexfec.ssrc == 0) {
132 RTC_LOG(LS_WARNING) << "FlexFEC is enabled, but no FlexFEC SSRC given. "
133 "Therefore disabling FlexFEC.";
134 return nullptr;
135 }
136 if (rtp.flexfec.protected_media_ssrcs.empty()) {
137 RTC_LOG(LS_WARNING)
138 << "FlexFEC is enabled, but no protected media SSRC given. "
139 "Therefore disabling FlexFEC.";
140 return nullptr;
141 }
142
143 if (rtp.flexfec.protected_media_ssrcs.size() > 1) {
144 RTC_LOG(LS_WARNING)
145 << "The supplied FlexfecConfig contained multiple protected "
146 "media streams, but our implementation currently only "
147 "supports protecting a single media stream. "
148 "To avoid confusion, disabling FlexFEC completely.";
149 return nullptr;
150 }
151
152 const RtpState* rtp_state = nullptr;
153 auto it = suspended_ssrcs.find(rtp.flexfec.ssrc);
154 if (it != suspended_ssrcs.end()) {
155 rtp_state = &it->second;
156 }
157
158 RTC_DCHECK_EQ(1U, rtp.flexfec.protected_media_ssrcs.size());
159 return absl::make_unique<FlexfecSender>(
160 rtp.flexfec.payload_type, rtp.flexfec.ssrc,
161 rtp.flexfec.protected_media_ssrcs[0], rtp.mid, rtp.extensions,
162 RTPSender::FecExtensionSizes(), rtp_state, Clock::GetRealTimeClock());
163}
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200164
165uint32_t CalculateOverheadRateBps(int packets_per_second,
166 size_t overhead_bytes_per_packet,
167 uint32_t max_overhead_bps) {
168 uint32_t overhead_bps =
169 static_cast<uint32_t>(8 * overhead_bytes_per_packet * packets_per_second);
170 return std::min(overhead_bps, max_overhead_bps);
171}
172
173int CalculatePacketRate(uint32_t bitrate_bps, size_t packet_size_bytes) {
174 size_t packet_size_bits = 8 * packet_size_bytes;
175 // Ceil for int value of bitrate_bps / packet_size_bits.
176 return static_cast<int>((bitrate_bps + packet_size_bits - 1) /
177 packet_size_bits);
178}
kjellander02b3d272016-04-20 05:05:54 -0700179} // namespace
180
Stefan Holmer9416ef82018-07-19 10:34:38 +0200181RtpVideoSender::RtpVideoSender(
Stefan Holmer9416ef82018-07-19 10:34:38 +0200182 std::map<uint32_t, RtpState> suspended_ssrcs,
183 const std::map<uint32_t, RtpPayloadState>& states,
184 const RtpConfig& rtp_config,
Jiawei Ou55718122018-11-09 13:17:39 -0800185 int rtcp_report_interval_ms,
Stefan Holmer9416ef82018-07-19 10:34:38 +0200186 Transport* send_transport,
187 const RtpSenderObservers& observers,
188 RtpTransportControllerSendInterface* transport,
189 RtcEventLog* event_log,
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200190 RateLimiter* retransmission_limiter,
Benjamin Wright192eeec2018-10-17 17:27:25 -0700191 std::unique_ptr<FecController> fec_controller,
192 FrameEncryptorInterface* frame_encryptor,
193 const CryptoOptions& crypto_options)
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200194 : send_side_bwe_with_overhead_(
195 webrtc::field_trial::IsEnabled("WebRTC-SendSideBwe-WithOverhead")),
Erik Språngc12d41b2019-01-09 09:55:31 +0100196 account_for_packetization_overhead_(!webrtc::field_trial::IsDisabled(
197 "WebRTC-SubtractPacketizationOverhead")),
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200198 active_(false),
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200199 module_process_thread_(nullptr),
200 suspended_ssrcs_(std::move(suspended_ssrcs)),
201 flexfec_sender_(MaybeCreateFlexfecSender(rtp_config, suspended_ssrcs_)),
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200202 fec_controller_(std::move(fec_controller)),
Amit Hilbuch0fc28432018-12-18 13:01:47 -0800203 rtp_modules_(CreateRtpRtcpModules(rtp_config,
Jiawei Ou55718122018-11-09 13:17:39 -0800204 rtcp_report_interval_ms,
Johannes Kron9190b822018-10-29 11:22:05 +0100205 send_transport,
206 observers.intra_frame_callback,
207 transport->GetBandwidthObserver(),
208 transport,
209 observers.rtcp_rtt_stats,
210 flexfec_sender_.get(),
211 observers.bitrate_observer,
212 observers.frame_count_observer,
213 observers.rtcp_type_observer,
214 observers.send_delay_observer,
215 observers.send_packet_observer,
216 event_log,
217 retransmission_limiter,
218 this,
219 transport->keepalive_config(),
220 frame_encryptor,
221 crypto_options)),
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200222 rtp_config_(rtp_config),
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200223 transport_(transport),
224 transport_overhead_bytes_per_packet_(0),
225 overhead_bytes_per_packet_(0),
226 encoder_target_rate_bps_(0) {
Amit Hilbuch0fc28432018-12-18 13:01:47 -0800227 RTC_DCHECK_EQ(rtp_config.ssrcs.size(), rtp_modules_.size());
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200228 module_process_thread_checker_.DetachFromThread();
Åsa Persson4bece9a2017-10-06 10:04:04 +0200229 // SSRCs are assumed to be sorted in the same order as |rtp_modules|.
Amit Hilbuch0fc28432018-12-18 13:01:47 -0800230 for (uint32_t ssrc : rtp_config.ssrcs) {
Åsa Persson4bece9a2017-10-06 10:04:04 +0200231 // Restore state if it previously existed.
232 const RtpPayloadState* state = nullptr;
233 auto it = states.find(ssrc);
234 if (it != states.end()) {
235 state = &it->second;
philipel25d31ec2018-08-08 16:33:01 +0200236 shared_frame_id_ = std::max(shared_frame_id_, state->shared_frame_id);
Åsa Persson4bece9a2017-10-06 10:04:04 +0200237 }
238 params_.push_back(RtpPayloadParams(ssrc, state));
239 }
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200240
241 // RTP/RTCP initialization.
242
243 // We add the highest spatial layer first to ensure it'll be prioritized
244 // when sending padding, with the hope that the packet rate will be smaller,
245 // and that it's more important to protect than the lower layers.
Niels Möller2ff1f2a2018-08-09 16:16:34 +0200246
247 // TODO(nisse): Consider moving registration with PacketRouter last, after the
248 // modules are fully configured.
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200249 for (auto& rtp_rtcp : rtp_modules_) {
250 constexpr bool remb_candidate = true;
251 transport->packet_router()->AddSendRtpModule(rtp_rtcp.get(),
252 remb_candidate);
253 }
254
255 for (size_t i = 0; i < rtp_config_.extensions.size(); ++i) {
256 const std::string& extension = rtp_config_.extensions[i].uri;
257 int id = rtp_config_.extensions[i].id;
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200258 RTC_DCHECK(RtpExtension::IsSupportedForVideo(extension));
259 for (auto& rtp_rtcp : rtp_modules_) {
Danil Chapovalov585d1aa2018-09-14 18:29:32 +0200260 RTC_CHECK(rtp_rtcp->RegisterRtpHeaderExtension(extension, id));
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200261 }
262 }
263
264 ConfigureProtection(rtp_config);
265 ConfigureSsrcs(rtp_config);
Amit Hilbuch77938e62018-12-21 09:23:38 -0800266 ConfigureRids(rtp_config);
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200267
268 if (!rtp_config.mid.empty()) {
269 for (auto& rtp_rtcp : rtp_modules_) {
270 rtp_rtcp->SetMid(rtp_config.mid);
271 }
272 }
273
274 // TODO(pbos): Should we set CNAME on all RTP modules?
275 rtp_modules_.front()->SetCNAME(rtp_config.c_name.c_str());
276
277 for (auto& rtp_rtcp : rtp_modules_) {
278 rtp_rtcp->RegisterRtcpStatisticsCallback(observers.rtcp_stats);
279 rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(observers.rtp_stats);
280 rtp_rtcp->SetMaxRtpPacketSize(rtp_config.max_packet_size);
281 rtp_rtcp->RegisterVideoSendPayload(rtp_config.payload_type,
282 rtp_config.payload_name.c_str());
283 }
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200284 // Currently, both ULPFEC and FlexFEC use the same FEC rate calculation logic,
285 // so enable that logic if either of those FEC schemes are enabled.
286 fec_controller_->SetProtectionMethod(FecEnabled(), NackEnabled());
287
288 fec_controller_->SetProtectionCallback(this);
289 // Signal congestion controller this object is ready for OnPacket* callbacks.
290 if (fec_controller_->UseLossVectorMask()) {
291 transport_->RegisterPacketFeedbackObserver(this);
292 }
Per83d09102016-04-15 14:59:13 +0200293}
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000294
Stefan Holmer9416ef82018-07-19 10:34:38 +0200295RtpVideoSender::~RtpVideoSender() {
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200296 for (auto& rtp_rtcp : rtp_modules_) {
297 transport_->packet_router()->RemoveSendRtpModule(rtp_rtcp.get());
298 }
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200299 if (fec_controller_->UseLossVectorMask()) {
300 transport_->DeRegisterPacketFeedbackObserver(this);
301 }
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200302}
303
Stefan Holmer9416ef82018-07-19 10:34:38 +0200304void RtpVideoSender::RegisterProcessThread(
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200305 ProcessThread* module_process_thread) {
306 RTC_DCHECK_RUN_ON(&module_process_thread_checker_);
307 RTC_DCHECK(!module_process_thread_);
308 module_process_thread_ = module_process_thread;
309
310 for (auto& rtp_rtcp : rtp_modules_)
311 module_process_thread_->RegisterModule(rtp_rtcp.get(), RTC_FROM_HERE);
312}
313
Stefan Holmer9416ef82018-07-19 10:34:38 +0200314void RtpVideoSender::DeRegisterProcessThread() {
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200315 RTC_DCHECK_RUN_ON(&module_process_thread_checker_);
316 for (auto& rtp_rtcp : rtp_modules_)
317 module_process_thread_->DeRegisterModule(rtp_rtcp.get());
318}
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000319
Stefan Holmer9416ef82018-07-19 10:34:38 +0200320void RtpVideoSender::SetActive(bool active) {
Tommi97888bd2016-01-21 23:24:59 +0100321 rtc::CritScope lock(&crit_);
Peter Boström8b79b072016-02-26 16:31:37 +0100322 if (active_ == active)
323 return;
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800324 const std::vector<bool> active_modules(rtp_modules_.size(), active);
325 SetActiveModules(active_modules);
326}
Per512ecb32016-09-23 15:52:06 +0200327
Stefan Holmer9416ef82018-07-19 10:34:38 +0200328void RtpVideoSender::SetActiveModules(const std::vector<bool> active_modules) {
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800329 rtc::CritScope lock(&crit_);
330 RTC_DCHECK_EQ(rtp_modules_.size(), active_modules.size());
331 active_ = false;
332 for (size_t i = 0; i < active_modules.size(); ++i) {
333 if (active_modules[i]) {
334 active_ = true;
335 }
336 // Sends a kRtcpByeCode when going from true to false.
337 rtp_modules_[i]->SetSendingStatus(active_modules[i]);
338 // If set to false this module won't send media.
339 rtp_modules_[i]->SetSendingMediaStatus(active_modules[i]);
Per512ecb32016-09-23 15:52:06 +0200340 }
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000341}
342
Stefan Holmer9416ef82018-07-19 10:34:38 +0200343bool RtpVideoSender::IsActive() {
Tommi97888bd2016-01-21 23:24:59 +0100344 rtc::CritScope lock(&crit_);
mflodman@webrtc.org47d657b2015-02-19 10:29:32 +0000345 return active_ && !rtp_modules_.empty();
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000346}
347
Stefan Holmer9416ef82018-07-19 10:34:38 +0200348EncodedImageCallback::Result RtpVideoSender::OnEncodedImage(
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700349 const EncodedImage& encoded_image,
350 const CodecSpecificInfo* codec_specific_info,
351 const RTPFragmentationHeader* fragmentation) {
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200352 fec_controller_->UpdateWithEncodedData(encoded_image._length,
353 encoded_image._frameType);
Tommi97888bd2016-01-21 23:24:59 +0100354 rtc::CritScope lock(&crit_);
Peter Boström8b79b072016-02-26 16:31:37 +0100355 RTC_DCHECK(!rtp_modules_.empty());
Per512ecb32016-09-23 15:52:06 +0200356 if (!active_)
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700357 return Result(Result::ERROR_SEND_FAILED);
mflodman@webrtc.org50e28162015-02-23 07:45:11 +0000358
philipelbf2b6202018-08-27 14:33:18 +0200359 shared_frame_id_++;
Niels Möllerd3b8c632018-08-27 15:33:42 +0200360 size_t stream_index = 0;
361 if (codec_specific_info &&
362 (codec_specific_info->codecType == kVideoCodecVP8 ||
363 codec_specific_info->codecType == kVideoCodecH264 ||
364 codec_specific_info->codecType == kVideoCodecGeneric)) {
365 // Map spatial index to simulcast.
366 stream_index = encoded_image.SpatialIndex().value_or(0);
367 }
sergeyu7b9feee2016-11-17 16:16:14 -0800368 RTC_DCHECK_LT(stream_index, rtp_modules_.size());
Stefan Holmerf7044682018-07-17 10:16:41 +0200369 RTPVideoHeader rtp_video_header = params_[stream_index].GetRtpVideoHeader(
philipelbf2b6202018-08-27 14:33:18 +0200370 encoded_image, codec_specific_info, shared_frame_id_);
Niels Möllerbb894ff2018-03-15 12:28:53 +0100371
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700372 uint32_t frame_id;
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800373 if (!rtp_modules_[stream_index]->Sending()) {
374 // The payload router could be active but this module isn't sending.
375 return Result(Result::ERROR_SEND_FAILED);
376 }
sergeyu7b9feee2016-11-17 16:16:14 -0800377 bool send_result = rtp_modules_[stream_index]->SendOutgoingData(
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200378 encoded_image._frameType, rtp_config_.payload_type,
Niels Möller23775882018-08-16 10:24:12 +0200379 encoded_image.Timestamp(), encoded_image.capture_time_ms_,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200380 encoded_image._buffer, encoded_image._length, fragmentation,
381 &rtp_video_header, &frame_id);
sergeyu7b9feee2016-11-17 16:16:14 -0800382 if (!send_result)
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700383 return Result(Result::ERROR_SEND_FAILED);
384
385 return Result(Result::OK, frame_id);
mflodman@webrtc.orga4ef2ce2015-02-12 09:54:18 +0000386}
387
Stefan Holmer9416ef82018-07-19 10:34:38 +0200388void RtpVideoSender::OnBitrateAllocationUpdated(
Erik Språng566124a2018-04-23 12:32:22 +0200389 const VideoBitrateAllocation& bitrate) {
sprang1a646ee2016-12-01 06:34:11 -0800390 rtc::CritScope lock(&crit_);
391 if (IsActive()) {
392 if (rtp_modules_.size() == 1) {
393 // If spatial scalability is enabled, it is covered by a single stream.
394 rtp_modules_[0]->SetVideoBitrateAllocation(bitrate);
395 } else {
Stefan Holmerf7044682018-07-17 10:16:41 +0200396 std::vector<absl::optional<VideoBitrateAllocation>> layer_bitrates =
397 bitrate.GetSimulcastAllocations();
Erik Språng566124a2018-04-23 12:32:22 +0200398 // Simulcast is in use, split the VideoBitrateAllocation into one struct
399 // per rtp stream, moving over the temporal layer allocation.
Stefan Holmerf7044682018-07-17 10:16:41 +0200400 for (size_t i = 0; i < rtp_modules_.size(); ++i) {
401 // The next spatial layer could be used if the current one is
402 // inactive.
403 if (layer_bitrates[i]) {
404 rtp_modules_[i]->SetVideoBitrateAllocation(*layer_bitrates[i]);
Ilya Nikolaevskiyb0588e62018-08-27 14:12:27 +0200405 } else {
406 // Signal a 0 bitrate on a simulcast stream.
407 rtp_modules_[i]->SetVideoBitrateAllocation(VideoBitrateAllocation());
Seth Hampson46e31ba2018-01-18 10:39:54 -0800408 }
sprang1a646ee2016-12-01 06:34:11 -0800409 }
410 }
411 }
412}
413
Stefan Holmer9416ef82018-07-19 10:34:38 +0200414void RtpVideoSender::ConfigureProtection(const RtpConfig& rtp_config) {
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200415 // Consistency of FlexFEC parameters is checked in MaybeCreateFlexfecSender.
416 const bool flexfec_enabled = (flexfec_sender_ != nullptr);
417
418 // Consistency of NACK and RED+ULPFEC parameters is checked in this function.
419 const bool nack_enabled = rtp_config.nack.rtp_history_ms > 0;
420 int red_payload_type = rtp_config.ulpfec.red_payload_type;
421 int ulpfec_payload_type = rtp_config.ulpfec.ulpfec_payload_type;
422
423 // Shorthands.
424 auto IsRedEnabled = [&]() { return red_payload_type >= 0; };
425 auto IsUlpfecEnabled = [&]() { return ulpfec_payload_type >= 0; };
426 auto DisableRedAndUlpfec = [&]() {
427 red_payload_type = -1;
428 ulpfec_payload_type = -1;
429 };
430
431 if (webrtc::field_trial::IsEnabled("WebRTC-DisableUlpFecExperiment")) {
432 RTC_LOG(LS_INFO) << "Experiment to disable sending ULPFEC is enabled.";
433 DisableRedAndUlpfec();
434 }
435
436 // If enabled, FlexFEC takes priority over RED+ULPFEC.
437 if (flexfec_enabled) {
438 if (IsUlpfecEnabled()) {
439 RTC_LOG(LS_INFO)
440 << "Both FlexFEC and ULPFEC are configured. Disabling ULPFEC.";
441 }
442 DisableRedAndUlpfec();
443 }
444
445 // Payload types without picture ID cannot determine that a stream is complete
446 // without retransmitting FEC, so using ULPFEC + NACK for H.264 (for instance)
447 // is a waste of bandwidth since FEC packets still have to be transmitted.
448 // Note that this is not the case with FlexFEC.
449 if (nack_enabled && IsUlpfecEnabled() &&
450 !PayloadTypeSupportsSkippingFecPackets(rtp_config.payload_name)) {
451 RTC_LOG(LS_WARNING)
452 << "Transmitting payload type without picture ID using "
453 "NACK+ULPFEC is a waste of bandwidth since ULPFEC packets "
454 "also have to be retransmitted. Disabling ULPFEC.";
455 DisableRedAndUlpfec();
456 }
457
458 // Verify payload types.
459 if (IsUlpfecEnabled() ^ IsRedEnabled()) {
460 RTC_LOG(LS_WARNING)
461 << "Only RED or only ULPFEC enabled, but not both. Disabling both.";
462 DisableRedAndUlpfec();
463 }
464
465 for (auto& rtp_rtcp : rtp_modules_) {
466 // Set NACK.
467 rtp_rtcp->SetStorePacketsStatus(true, kMinSendSidePacketHistorySize);
468 // Set RED/ULPFEC information.
469 rtp_rtcp->SetUlpfecConfig(red_payload_type, ulpfec_payload_type);
470 }
471}
472
Stefan Holmer9416ef82018-07-19 10:34:38 +0200473bool RtpVideoSender::FecEnabled() const {
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200474 const bool flexfec_enabled = (flexfec_sender_ != nullptr);
Emircan Uysalera7af0212018-09-22 19:11:29 -0400475 const bool ulpfec_enabled =
476 !webrtc::field_trial::IsEnabled("WebRTC-DisableUlpFecExperiment") &&
477 (rtp_config_.ulpfec.ulpfec_payload_type >= 0);
478 return flexfec_enabled || ulpfec_enabled;
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200479}
480
Stefan Holmer9416ef82018-07-19 10:34:38 +0200481bool RtpVideoSender::NackEnabled() const {
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200482 const bool nack_enabled = rtp_config_.nack.rtp_history_ms > 0;
483 return nack_enabled;
484}
485
Erik Språng482b3ef2019-01-08 16:19:11 +0100486uint32_t RtpVideoSender::GetPacketizationOverheadRate() const {
487 uint32_t packetization_overhead_bps = 0;
488 for (auto& rtp_rtcp : rtp_modules_) {
489 if (rtp_rtcp->SendingMedia()) {
490 packetization_overhead_bps += rtp_rtcp->PacketizationOverheadBps();
491 }
492 }
493 return packetization_overhead_bps;
494}
495
Stefan Holmer9416ef82018-07-19 10:34:38 +0200496void RtpVideoSender::DeliverRtcp(const uint8_t* packet, size_t length) {
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200497 // Runs on a network thread.
498 for (auto& rtp_rtcp : rtp_modules_)
499 rtp_rtcp->IncomingRtcpPacket(packet, length);
500}
501
Stefan Holmer9416ef82018-07-19 10:34:38 +0200502void RtpVideoSender::ConfigureSsrcs(const RtpConfig& rtp_config) {
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200503 // Configure regular SSRCs.
504 for (size_t i = 0; i < rtp_config.ssrcs.size(); ++i) {
505 uint32_t ssrc = rtp_config.ssrcs[i];
506 RtpRtcp* const rtp_rtcp = rtp_modules_[i].get();
507 rtp_rtcp->SetSSRC(ssrc);
508
509 // Restore RTP state if previous existed.
510 auto it = suspended_ssrcs_.find(ssrc);
511 if (it != suspended_ssrcs_.end())
512 rtp_rtcp->SetRtpState(it->second);
513 }
514
515 // Set up RTX if available.
516 if (rtp_config.rtx.ssrcs.empty())
517 return;
518
519 // Configure RTX SSRCs.
520 RTC_DCHECK_EQ(rtp_config.rtx.ssrcs.size(), rtp_config.ssrcs.size());
521 for (size_t i = 0; i < rtp_config.rtx.ssrcs.size(); ++i) {
522 uint32_t ssrc = rtp_config.rtx.ssrcs[i];
523 RtpRtcp* const rtp_rtcp = rtp_modules_[i].get();
524 rtp_rtcp->SetRtxSsrc(ssrc);
525 auto it = suspended_ssrcs_.find(ssrc);
526 if (it != suspended_ssrcs_.end())
527 rtp_rtcp->SetRtxState(it->second);
528 }
529
530 // Configure RTX payload types.
531 RTC_DCHECK_GE(rtp_config.rtx.payload_type, 0);
532 for (auto& rtp_rtcp : rtp_modules_) {
533 rtp_rtcp->SetRtxSendPayloadType(rtp_config.rtx.payload_type,
534 rtp_config.payload_type);
535 rtp_rtcp->SetRtxSendStatus(kRtxRetransmitted | kRtxRedundantPayloads);
536 }
537 if (rtp_config.ulpfec.red_payload_type != -1 &&
538 rtp_config.ulpfec.red_rtx_payload_type != -1) {
539 for (auto& rtp_rtcp : rtp_modules_) {
540 rtp_rtcp->SetRtxSendPayloadType(rtp_config.ulpfec.red_rtx_payload_type,
541 rtp_config.ulpfec.red_payload_type);
542 }
543 }
544}
545
Amit Hilbuch77938e62018-12-21 09:23:38 -0800546void RtpVideoSender::ConfigureRids(const RtpConfig& rtp_config) {
547 RTC_DCHECK(rtp_config.rids.empty() ||
548 rtp_config.rids.size() == rtp_config.ssrcs.size());
549 RTC_DCHECK(rtp_config.rids.empty() ||
550 rtp_config.rids.size() == rtp_modules_.size());
551 for (size_t i = 0; i < rtp_config.rids.size(); ++i) {
552 const std::string& rid = rtp_config.rids[i];
553 RtpRtcp* const rtp_rtcp = rtp_modules_[i].get();
554 rtp_rtcp->SetRid(rid);
555 }
556}
557
Stefan Holmer9416ef82018-07-19 10:34:38 +0200558void RtpVideoSender::OnNetworkAvailability(bool network_available) {
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200559 for (auto& rtp_rtcp : rtp_modules_) {
560 rtp_rtcp->SetRTCPStatus(network_available ? rtp_config_.rtcp_mode
561 : RtcpMode::kOff);
562 }
563}
564
Stefan Holmer9416ef82018-07-19 10:34:38 +0200565std::map<uint32_t, RtpState> RtpVideoSender::GetRtpStates() const {
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200566 std::map<uint32_t, RtpState> rtp_states;
567
568 for (size_t i = 0; i < rtp_config_.ssrcs.size(); ++i) {
569 uint32_t ssrc = rtp_config_.ssrcs[i];
570 RTC_DCHECK_EQ(ssrc, rtp_modules_[i]->SSRC());
571 rtp_states[ssrc] = rtp_modules_[i]->GetRtpState();
572 }
573
574 for (size_t i = 0; i < rtp_config_.rtx.ssrcs.size(); ++i) {
575 uint32_t ssrc = rtp_config_.rtx.ssrcs[i];
576 rtp_states[ssrc] = rtp_modules_[i]->GetRtxState();
577 }
578
579 if (flexfec_sender_) {
580 uint32_t ssrc = rtp_config_.flexfec.ssrc;
581 rtp_states[ssrc] = flexfec_sender_->GetRtpState();
582 }
583
584 return rtp_states;
585}
586
Stefan Holmer9416ef82018-07-19 10:34:38 +0200587std::map<uint32_t, RtpPayloadState> RtpVideoSender::GetRtpPayloadStates()
588 const {
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200589 rtc::CritScope lock(&crit_);
590 std::map<uint32_t, RtpPayloadState> payload_states;
591 for (const auto& param : params_) {
592 payload_states[param.ssrc()] = param.state();
philipel25d31ec2018-08-08 16:33:01 +0200593 payload_states[param.ssrc()].shared_frame_id = shared_frame_id_;
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200594 }
595 return payload_states;
596}
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200597
598void RtpVideoSender::OnTransportOverheadChanged(
599 size_t transport_overhead_bytes_per_packet) {
600 rtc::CritScope lock(&crit_);
601 transport_overhead_bytes_per_packet_ = transport_overhead_bytes_per_packet;
602
603 size_t max_rtp_packet_size =
604 std::min(rtp_config_.max_packet_size,
605 kPathMTU - transport_overhead_bytes_per_packet_);
606 for (auto& rtp_rtcp : rtp_modules_) {
607 rtp_rtcp->SetMaxRtpPacketSize(max_rtp_packet_size);
608 }
609}
610
611void RtpVideoSender::OnOverheadChanged(size_t overhead_bytes_per_packet) {
612 rtc::CritScope lock(&crit_);
613 overhead_bytes_per_packet_ = overhead_bytes_per_packet;
614}
615
616void RtpVideoSender::OnBitrateUpdated(uint32_t bitrate_bps,
617 uint8_t fraction_loss,
618 int64_t rtt,
619 int framerate) {
620 // Substract overhead from bitrate.
621 rtc::CritScope lock(&crit_);
622 uint32_t payload_bitrate_bps = bitrate_bps;
623 if (send_side_bwe_with_overhead_) {
Bjorn Terelius25068392018-10-25 11:07:29 +0200624 uint32_t overhead_bps = CalculateOverheadRateBps(
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200625 CalculatePacketRate(
626 bitrate_bps,
627 rtp_config_.max_packet_size + transport_overhead_bytes_per_packet_),
628 overhead_bytes_per_packet_ + transport_overhead_bytes_per_packet_,
629 bitrate_bps);
Bjorn Terelius25068392018-10-25 11:07:29 +0200630 RTC_DCHECK_LE(overhead_bps, bitrate_bps);
631 payload_bitrate_bps = bitrate_bps - overhead_bps;
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200632 }
633
634 // Get the encoder target rate. It is the estimated network rate -
635 // protection overhead.
636 encoder_target_rate_bps_ = fec_controller_->UpdateFecRates(
637 payload_bitrate_bps, framerate, fraction_loss, loss_mask_vector_, rtt);
Erik Språng482b3ef2019-01-08 16:19:11 +0100638
Erik Språngc12d41b2019-01-09 09:55:31 +0100639 if (account_for_packetization_overhead_) {
640 // Subtract packetization overhead from the encoder target. If rate is
641 // really low, cap the overhead at 50%. Since packetization is measured over
642 // an averaging window, it might intermittently be higher than encoder
643 // target (eg encoder pause event), so cap it to target.
644 const uint32_t packetization_rate_bps =
645 std::min(GetPacketizationOverheadRate(), encoder_target_rate_bps_);
646 encoder_target_rate_bps_ =
647 std::max(encoder_target_rate_bps_ - packetization_rate_bps,
648 encoder_target_rate_bps_ / 2);
649 }
Erik Språng482b3ef2019-01-08 16:19:11 +0100650
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200651 loss_mask_vector_.clear();
652
653 uint32_t encoder_overhead_rate_bps =
654 send_side_bwe_with_overhead_
655 ? CalculateOverheadRateBps(
656 CalculatePacketRate(encoder_target_rate_bps_,
657 rtp_config_.max_packet_size +
658 transport_overhead_bytes_per_packet_ -
659 overhead_bytes_per_packet_),
660 overhead_bytes_per_packet_ +
661 transport_overhead_bytes_per_packet_,
662 bitrate_bps - encoder_target_rate_bps_)
663 : 0;
664
665 // When the field trial "WebRTC-SendSideBwe-WithOverhead" is enabled
666 // protection_bitrate includes overhead.
667 protection_bitrate_bps_ =
668 bitrate_bps - (encoder_target_rate_bps_ + encoder_overhead_rate_bps);
669}
670
671uint32_t RtpVideoSender::GetPayloadBitrateBps() const {
672 return encoder_target_rate_bps_;
673}
674
675uint32_t RtpVideoSender::GetProtectionBitrateBps() const {
676 return protection_bitrate_bps_;
677}
678
679int RtpVideoSender::ProtectionRequest(const FecProtectionParams* delta_params,
680 const FecProtectionParams* key_params,
681 uint32_t* sent_video_rate_bps,
682 uint32_t* sent_nack_rate_bps,
683 uint32_t* sent_fec_rate_bps) {
684 *sent_video_rate_bps = 0;
685 *sent_nack_rate_bps = 0;
686 *sent_fec_rate_bps = 0;
687 for (auto& rtp_rtcp : rtp_modules_) {
688 uint32_t not_used = 0;
689 uint32_t module_video_rate = 0;
690 uint32_t module_fec_rate = 0;
691 uint32_t module_nack_rate = 0;
692 rtp_rtcp->SetFecParameters(*delta_params, *key_params);
693 rtp_rtcp->BitrateSent(&not_used, &module_video_rate, &module_fec_rate,
694 &module_nack_rate);
695 *sent_video_rate_bps += module_video_rate;
696 *sent_nack_rate_bps += module_nack_rate;
697 *sent_fec_rate_bps += module_fec_rate;
698 }
699 return 0;
700}
701
702void RtpVideoSender::OnPacketAdded(uint32_t ssrc, uint16_t seq_num) {
703 const auto ssrcs = rtp_config_.ssrcs;
704 if (std::find(ssrcs.begin(), ssrcs.end(), ssrc) != ssrcs.end()) {
705 feedback_packet_seq_num_set_.insert(seq_num);
706 if (feedback_packet_seq_num_set_.size() > kSendSideSeqNumSetMaxSize) {
707 RTC_LOG(LS_WARNING) << "Feedback packet sequence number set exceed it's "
708 "max size', will get reset.";
709 feedback_packet_seq_num_set_.clear();
710 }
711 }
712}
713
714void RtpVideoSender::OnPacketFeedbackVector(
715 const std::vector<PacketFeedback>& packet_feedback_vector) {
716 rtc::CritScope lock(&crit_);
717 // Lost feedbacks are not considered to be lost packets.
718 for (const PacketFeedback& packet : packet_feedback_vector) {
719 auto it = feedback_packet_seq_num_set_.find(packet.sequence_number);
720 if (it != feedback_packet_seq_num_set_.end()) {
721 const bool lost = packet.arrival_time_ms == PacketFeedback::kNotReceived;
722 loss_mask_vector_.push_back(lost);
723 feedback_packet_seq_num_set_.erase(it);
724 }
725 }
726}
727
728void RtpVideoSender::SetEncodingData(size_t width,
729 size_t height,
730 size_t num_temporal_layers) {
731 fec_controller_->SetEncodingData(width, height, num_temporal_layers,
732 rtp_config_.max_packet_size);
733}
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000734} // namespace webrtc