blob: cd9283e2a11eed87a888d82abaf16197504a8f7e [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"
Niels Möller5fe95102019-03-04 16:49:25 +010019#include "api/transport/field_trial_based_config.h"
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020020#include "call/rtp_transport_controller_send_interface.h"
21#include "modules/pacing/packet_router.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020022#include "modules/rtp_rtcp/include/rtp_rtcp.h"
23#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
Niels Möller5fe95102019-03-04 16:49:25 +010024#include "modules/rtp_rtcp/source/playout_delay_oracle.h"
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020025#include "modules/rtp_rtcp/source/rtp_sender.h"
26#include "modules/utility/include/process_thread.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020027#include "modules/video_coding/include/video_codec_interface.h"
28#include "rtc_base/checks.h"
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020029#include "rtc_base/location.h"
30#include "rtc_base/logging.h"
31#include "system_wrappers/include/field_trial.h"
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +000032
33namespace webrtc {
34
Niels Möller5fe95102019-03-04 16:49:25 +010035namespace webrtc_internal_rtp_video_sender {
36
37RtpStreamSender::RtpStreamSender(
38 std::unique_ptr<PlayoutDelayOracle> playout_delay_oracle,
39 std::unique_ptr<RtpRtcp> rtp_rtcp,
40 std::unique_ptr<RTPSenderVideo> sender_video)
41 : playout_delay_oracle(std::move(playout_delay_oracle)),
42 rtp_rtcp(std::move(rtp_rtcp)),
43 sender_video(std::move(sender_video)) {}
44
45RtpStreamSender::~RtpStreamSender() = default;
46
47} // namespace webrtc_internal_rtp_video_sender
48
kjellander02b3d272016-04-20 05:05:54 -070049namespace {
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020050static const int kMinSendSidePacketHistorySize = 600;
Stefan Holmer64be7fa2018-10-04 15:21:55 +020051// Assume an average video stream has around 3 packets per frame (1 mbps / 30
52// fps / 1400B) A sequence number set with size 5500 will be able to store
53// packet sequence number for at least last 60 seconds.
54static const int kSendSideSeqNumSetMaxSize = 5500;
55// 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 16:03:46 +020057
Niels Möller5fe95102019-03-04 16:49:25 +010058using webrtc_internal_rtp_video_sender::RtpStreamSender;
59
60std::vector<RtpStreamSender> CreateRtpStreamSenders(
Sebastian Jansson572c60f2019-03-04 18:30:41 +010061 Clock* clock,
Johannes Kron9190b822018-10-29 11:22:05 +010062 const RtpConfig& rtp_config,
Jiawei Ou55718122018-11-09 13:17:39 -080063 int rtcp_report_interval_ms,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020064 Transport* send_transport,
65 RtcpIntraFrameObserver* intra_frame_callback,
66 RtcpBandwidthObserver* bandwidth_callback,
67 RtpTransportControllerSendInterface* transport,
68 RtcpRttStats* rtt_stats,
69 FlexfecSender* flexfec_sender,
70 BitrateStatisticsObserver* bitrate_observer,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020071 RtcpPacketTypeCounterObserver* rtcp_type_observer,
72 SendSideDelayObserver* send_delay_observer,
73 SendPacketObserver* send_packet_observer,
74 RtcEventLog* event_log,
75 RateLimiter* retransmission_rate_limiter,
76 OverheadObserver* overhead_observer,
Benjamin Wright192eeec2018-10-17 17:27:25 -070077 FrameEncryptorInterface* frame_encryptor,
78 const CryptoOptions& crypto_options) {
Amit Hilbuch0fc28432018-12-18 13:01:47 -080079 RTC_DCHECK_GT(rtp_config.ssrcs.size(), 0);
Benjamin Wright192eeec2018-10-17 17:27:25 -070080
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020081 RtpRtcp::Configuration configuration;
Sebastian Jansson572c60f2019-03-04 18:30:41 +010082 configuration.clock = clock;
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020083 configuration.audio = false;
84 configuration.receiver_only = false;
85 configuration.outgoing_transport = send_transport;
86 configuration.intra_frame_callback = intra_frame_callback;
87 configuration.bandwidth_callback = bandwidth_callback;
88 configuration.transport_feedback_callback =
89 transport->transport_feedback_observer();
90 configuration.rtt_stats = rtt_stats;
91 configuration.rtcp_packet_type_counter_observer = rtcp_type_observer;
92 configuration.paced_sender = transport->packet_sender();
93 configuration.transport_sequence_number_allocator =
94 transport->packet_router();
95 configuration.send_bitrate_observer = bitrate_observer;
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020096 configuration.send_side_delay_observer = send_delay_observer;
97 configuration.send_packet_observer = send_packet_observer;
98 configuration.event_log = event_log;
99 configuration.retransmission_rate_limiter = retransmission_rate_limiter;
100 configuration.overhead_observer = overhead_observer;
Benjamin Wright192eeec2018-10-17 17:27:25 -0700101 configuration.frame_encryptor = frame_encryptor;
102 configuration.require_frame_encryption =
103 crypto_options.sframe.require_frame_encryption;
Johannes Kron9190b822018-10-29 11:22:05 +0100104 configuration.extmap_allow_mixed = rtp_config.extmap_allow_mixed;
Jiawei Ou8b5d9d82018-11-15 16:44:37 -0800105 configuration.rtcp_report_interval_ms = rtcp_report_interval_ms;
Benjamin Wright192eeec2018-10-17 17:27:25 -0700106
Niels Möller5fe95102019-03-04 16:49:25 +0100107 std::vector<RtpStreamSender> rtp_streams;
Johannes Kron9190b822018-10-29 11:22:05 +0100108 const std::vector<uint32_t>& flexfec_protected_ssrcs =
109 rtp_config.flexfec.protected_media_ssrcs;
Amit Hilbuch0fc28432018-12-18 13:01:47 -0800110 for (uint32_t ssrc : rtp_config.ssrcs) {
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200111 bool enable_flexfec = flexfec_sender != nullptr &&
112 std::find(flexfec_protected_ssrcs.begin(),
113 flexfec_protected_ssrcs.end(),
114 ssrc) != flexfec_protected_ssrcs.end();
115 configuration.flexfec_sender = enable_flexfec ? flexfec_sender : nullptr;
Niels Möller5fe95102019-03-04 16:49:25 +0100116 auto playout_delay_oracle = absl::make_unique<PlayoutDelayOracle>();
117
118 configuration.ack_observer = playout_delay_oracle.get();
Danil Chapovalovc44f6cc2019-03-06 11:31:09 +0100119 auto rtp_rtcp = RtpRtcp::Create(configuration);
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200120 rtp_rtcp->SetSendingStatus(false);
121 rtp_rtcp->SetSendingMediaStatus(false);
122 rtp_rtcp->SetRTCPStatus(RtcpMode::kCompound);
Niels Möller5fe95102019-03-04 16:49:25 +0100123
124 auto sender_video = absl::make_unique<RTPSenderVideo>(
Niels Möllerbf40c382019-03-12 13:58:56 +0100125 configuration.clock, rtp_rtcp->RtpSender(),
126 configuration.flexfec_sender, playout_delay_oracle.get(),
127 frame_encryptor, crypto_options.sframe.require_frame_encryption,
Niels Möller5fe95102019-03-04 16:49:25 +0100128 FieldTrialBasedConfig());
129 rtp_streams.emplace_back(std::move(playout_delay_oracle),
130 std::move(rtp_rtcp), std::move(sender_video));
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200131 }
Niels Möller5fe95102019-03-04 16:49:25 +0100132 return rtp_streams;
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200133}
134
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200135bool PayloadTypeSupportsSkippingFecPackets(const std::string& payload_name) {
136 const VideoCodecType codecType = PayloadStringToCodecType(payload_name);
137 if (codecType == kVideoCodecVP8 || codecType == kVideoCodecVP9) {
138 return true;
139 }
Sami Kalliomäki22c7d692018-09-03 14:40:05 +0200140 if (codecType == kVideoCodecGeneric &&
141 field_trial::IsEnabled("WebRTC-GenericPictureId")) {
142 return true;
143 }
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200144 return false;
145}
146
147// TODO(brandtr): Update this function when we support multistream protection.
148std::unique_ptr<FlexfecSender> MaybeCreateFlexfecSender(
Sebastian Jansson572c60f2019-03-04 18:30:41 +0100149 Clock* clock,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200150 const RtpConfig& rtp,
151 const std::map<uint32_t, RtpState>& suspended_ssrcs) {
152 if (rtp.flexfec.payload_type < 0) {
153 return nullptr;
154 }
155 RTC_DCHECK_GE(rtp.flexfec.payload_type, 0);
156 RTC_DCHECK_LE(rtp.flexfec.payload_type, 127);
157 if (rtp.flexfec.ssrc == 0) {
158 RTC_LOG(LS_WARNING) << "FlexFEC is enabled, but no FlexFEC SSRC given. "
159 "Therefore disabling FlexFEC.";
160 return nullptr;
161 }
162 if (rtp.flexfec.protected_media_ssrcs.empty()) {
163 RTC_LOG(LS_WARNING)
164 << "FlexFEC is enabled, but no protected media SSRC given. "
165 "Therefore disabling FlexFEC.";
166 return nullptr;
167 }
168
169 if (rtp.flexfec.protected_media_ssrcs.size() > 1) {
170 RTC_LOG(LS_WARNING)
171 << "The supplied FlexfecConfig contained multiple protected "
172 "media streams, but our implementation currently only "
173 "supports protecting a single media stream. "
174 "To avoid confusion, disabling FlexFEC completely.";
175 return nullptr;
176 }
177
178 const RtpState* rtp_state = nullptr;
179 auto it = suspended_ssrcs.find(rtp.flexfec.ssrc);
180 if (it != suspended_ssrcs.end()) {
181 rtp_state = &it->second;
182 }
183
184 RTC_DCHECK_EQ(1U, rtp.flexfec.protected_media_ssrcs.size());
185 return absl::make_unique<FlexfecSender>(
186 rtp.flexfec.payload_type, rtp.flexfec.ssrc,
187 rtp.flexfec.protected_media_ssrcs[0], rtp.mid, rtp.extensions,
Sebastian Jansson572c60f2019-03-04 18:30:41 +0100188 RTPSender::FecExtensionSizes(), rtp_state, clock);
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200189}
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200190
191uint32_t CalculateOverheadRateBps(int packets_per_second,
192 size_t overhead_bytes_per_packet,
193 uint32_t max_overhead_bps) {
194 uint32_t overhead_bps =
195 static_cast<uint32_t>(8 * overhead_bytes_per_packet * packets_per_second);
196 return std::min(overhead_bps, max_overhead_bps);
197}
198
199int CalculatePacketRate(uint32_t bitrate_bps, size_t packet_size_bytes) {
200 size_t packet_size_bits = 8 * packet_size_bytes;
201 // Ceil for int value of bitrate_bps / packet_size_bits.
202 return static_cast<int>((bitrate_bps + packet_size_bits - 1) /
203 packet_size_bits);
204}
kjellander02b3d272016-04-20 05:05:54 -0700205} // namespace
206
Stefan Holmer9416ef82018-07-19 10:34:38 +0200207RtpVideoSender::RtpVideoSender(
Sebastian Jansson572c60f2019-03-04 18:30:41 +0100208 Clock* clock,
Stefan Holmer9416ef82018-07-19 10:34:38 +0200209 std::map<uint32_t, RtpState> suspended_ssrcs,
210 const std::map<uint32_t, RtpPayloadState>& states,
211 const RtpConfig& rtp_config,
Jiawei Ou55718122018-11-09 13:17:39 -0800212 int rtcp_report_interval_ms,
Stefan Holmer9416ef82018-07-19 10:34:38 +0200213 Transport* send_transport,
214 const RtpSenderObservers& observers,
215 RtpTransportControllerSendInterface* transport,
216 RtcEventLog* event_log,
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200217 RateLimiter* retransmission_limiter,
Benjamin Wright192eeec2018-10-17 17:27:25 -0700218 std::unique_ptr<FecController> fec_controller,
219 FrameEncryptorInterface* frame_encryptor,
220 const CryptoOptions& crypto_options)
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200221 : send_side_bwe_with_overhead_(
222 webrtc::field_trial::IsEnabled("WebRTC-SendSideBwe-WithOverhead")),
Erik Språngc12d41b2019-01-09 09:55:31 +0100223 account_for_packetization_overhead_(!webrtc::field_trial::IsDisabled(
224 "WebRTC-SubtractPacketizationOverhead")),
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200225 active_(false),
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200226 module_process_thread_(nullptr),
227 suspended_ssrcs_(std::move(suspended_ssrcs)),
Sebastian Jansson572c60f2019-03-04 18:30:41 +0100228 flexfec_sender_(
229 MaybeCreateFlexfecSender(clock, rtp_config, suspended_ssrcs_)),
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200230 fec_controller_(std::move(fec_controller)),
Sebastian Jansson572c60f2019-03-04 18:30:41 +0100231 rtp_streams_(CreateRtpStreamSenders(clock,
232 rtp_config,
Niels Möller5fe95102019-03-04 16:49:25 +0100233 rtcp_report_interval_ms,
234 send_transport,
235 observers.intra_frame_callback,
236 transport->GetBandwidthObserver(),
237 transport,
238 observers.rtcp_rtt_stats,
239 flexfec_sender_.get(),
240 observers.bitrate_observer,
241 observers.rtcp_type_observer,
242 observers.send_delay_observer,
243 observers.send_packet_observer,
244 event_log,
245 retransmission_limiter,
246 this,
Niels Möller5fe95102019-03-04 16:49:25 +0100247 frame_encryptor,
248 crypto_options)),
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200249 rtp_config_(rtp_config),
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200250 transport_(transport),
251 transport_overhead_bytes_per_packet_(0),
252 overhead_bytes_per_packet_(0),
Niels Möller949f0fd2019-01-29 09:44:24 +0100253 encoder_target_rate_bps_(0),
254 frame_counts_(rtp_config.ssrcs.size()),
Oleh Prypine8964902019-03-29 15:33:01 +0000255 frame_count_observer_(observers.frame_count_observer) {
Niels Möller5fe95102019-03-04 16:49:25 +0100256 RTC_DCHECK_EQ(rtp_config.ssrcs.size(), rtp_streams_.size());
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200257 module_process_thread_checker_.DetachFromThread();
Åsa Persson4bece9a2017-10-06 10:04:04 +0200258 // SSRCs are assumed to be sorted in the same order as |rtp_modules|.
Amit Hilbuch0fc28432018-12-18 13:01:47 -0800259 for (uint32_t ssrc : rtp_config.ssrcs) {
Åsa Persson4bece9a2017-10-06 10:04:04 +0200260 // Restore state if it previously existed.
261 const RtpPayloadState* state = nullptr;
262 auto it = states.find(ssrc);
263 if (it != states.end()) {
264 state = &it->second;
philipel25d31ec2018-08-08 16:33:01 +0200265 shared_frame_id_ = std::max(shared_frame_id_, state->shared_frame_id);
Åsa Persson4bece9a2017-10-06 10:04:04 +0200266 }
267 params_.push_back(RtpPayloadParams(ssrc, state));
268 }
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200269
270 // RTP/RTCP initialization.
271
272 // We add the highest spatial layer first to ensure it'll be prioritized
273 // when sending padding, with the hope that the packet rate will be smaller,
274 // and that it's more important to protect than the lower layers.
Niels Möller2ff1f2a2018-08-09 16:16:34 +0200275
276 // TODO(nisse): Consider moving registration with PacketRouter last, after the
277 // modules are fully configured.
Niels Möller5fe95102019-03-04 16:49:25 +0100278 for (const RtpStreamSender& stream : rtp_streams_) {
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200279 constexpr bool remb_candidate = true;
Niels Möller5fe95102019-03-04 16:49:25 +0100280 transport->packet_router()->AddSendRtpModule(stream.rtp_rtcp.get(),
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200281 remb_candidate);
282 }
283
284 for (size_t i = 0; i < rtp_config_.extensions.size(); ++i) {
285 const std::string& extension = rtp_config_.extensions[i].uri;
286 int id = rtp_config_.extensions[i].id;
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200287 RTC_DCHECK(RtpExtension::IsSupportedForVideo(extension));
Niels Möller5fe95102019-03-04 16:49:25 +0100288 for (const RtpStreamSender& stream : rtp_streams_) {
289 RTC_CHECK(stream.rtp_rtcp->RegisterRtpHeaderExtension(extension, id));
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200290 }
291 }
292
293 ConfigureProtection(rtp_config);
294 ConfigureSsrcs(rtp_config);
Amit Hilbuch77938e62018-12-21 09:23:38 -0800295 ConfigureRids(rtp_config);
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200296
297 if (!rtp_config.mid.empty()) {
Niels Möller5fe95102019-03-04 16:49:25 +0100298 for (const RtpStreamSender& stream : rtp_streams_) {
299 stream.rtp_rtcp->SetMid(rtp_config.mid);
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200300 }
301 }
302
Niels Möller5fe95102019-03-04 16:49:25 +0100303 for (const RtpStreamSender& stream : rtp_streams_) {
Amit Hilbuch38e6c662019-03-08 16:17:21 -0800304 // Simulcast has one module for each layer. Set the CNAME on all modules.
305 stream.rtp_rtcp->SetCNAME(rtp_config.c_name.c_str());
Niels Möller5fe95102019-03-04 16:49:25 +0100306 stream.rtp_rtcp->RegisterRtcpStatisticsCallback(observers.rtcp_stats);
307 stream.rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(
308 observers.rtp_stats);
309 stream.rtp_rtcp->SetMaxRtpPacketSize(rtp_config.max_packet_size);
310 stream.rtp_rtcp->RegisterSendPayloadFrequency(rtp_config.payload_type,
311 kVideoPayloadTypeFrequency);
312 stream.sender_video->RegisterPayloadType(rtp_config.payload_type,
313 rtp_config.payload_name);
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200314 }
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200315 // Currently, both ULPFEC and FlexFEC use the same FEC rate calculation logic,
316 // so enable that logic if either of those FEC schemes are enabled.
317 fec_controller_->SetProtectionMethod(FecEnabled(), NackEnabled());
318
319 fec_controller_->SetProtectionCallback(this);
320 // Signal congestion controller this object is ready for OnPacket* callbacks.
321 if (fec_controller_->UseLossVectorMask()) {
322 transport_->RegisterPacketFeedbackObserver(this);
323 }
Per83d09102016-04-15 14:59:13 +0200324}
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000325
Stefan Holmer9416ef82018-07-19 10:34:38 +0200326RtpVideoSender::~RtpVideoSender() {
Niels Möller5fe95102019-03-04 16:49:25 +0100327 for (const RtpStreamSender& stream : rtp_streams_) {
328 transport_->packet_router()->RemoveSendRtpModule(stream.rtp_rtcp.get());
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200329 }
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200330 if (fec_controller_->UseLossVectorMask()) {
331 transport_->DeRegisterPacketFeedbackObserver(this);
332 }
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200333}
334
Stefan Holmer9416ef82018-07-19 10:34:38 +0200335void RtpVideoSender::RegisterProcessThread(
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200336 ProcessThread* module_process_thread) {
337 RTC_DCHECK_RUN_ON(&module_process_thread_checker_);
338 RTC_DCHECK(!module_process_thread_);
339 module_process_thread_ = module_process_thread;
340
Niels Möller5fe95102019-03-04 16:49:25 +0100341 for (const RtpStreamSender& stream : rtp_streams_) {
342 module_process_thread_->RegisterModule(stream.rtp_rtcp.get(),
343 RTC_FROM_HERE);
344 }
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200345}
346
Stefan Holmer9416ef82018-07-19 10:34:38 +0200347void RtpVideoSender::DeRegisterProcessThread() {
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200348 RTC_DCHECK_RUN_ON(&module_process_thread_checker_);
Niels Möller5fe95102019-03-04 16:49:25 +0100349 for (const RtpStreamSender& stream : rtp_streams_)
350 module_process_thread_->DeRegisterModule(stream.rtp_rtcp.get());
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200351}
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000352
Stefan Holmer9416ef82018-07-19 10:34:38 +0200353void RtpVideoSender::SetActive(bool active) {
Tommi97888bd2016-01-21 23:24:59 +0100354 rtc::CritScope lock(&crit_);
Peter Boström8b79b072016-02-26 16:31:37 +0100355 if (active_ == active)
356 return;
Niels Möller5fe95102019-03-04 16:49:25 +0100357 const std::vector<bool> active_modules(rtp_streams_.size(), active);
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800358 SetActiveModules(active_modules);
359}
Per512ecb32016-09-23 15:52:06 +0200360
Stefan Holmer9416ef82018-07-19 10:34:38 +0200361void RtpVideoSender::SetActiveModules(const std::vector<bool> active_modules) {
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800362 rtc::CritScope lock(&crit_);
Niels Möller5fe95102019-03-04 16:49:25 +0100363 RTC_DCHECK_EQ(rtp_streams_.size(), active_modules.size());
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800364 active_ = false;
365 for (size_t i = 0; i < active_modules.size(); ++i) {
366 if (active_modules[i]) {
367 active_ = true;
368 }
369 // Sends a kRtcpByeCode when going from true to false.
Niels Möller5fe95102019-03-04 16:49:25 +0100370 rtp_streams_[i].rtp_rtcp->SetSendingStatus(active_modules[i]);
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800371 // If set to false this module won't send media.
Niels Möller5fe95102019-03-04 16:49:25 +0100372 rtp_streams_[i].rtp_rtcp->SetSendingMediaStatus(active_modules[i]);
Per512ecb32016-09-23 15:52:06 +0200373 }
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000374}
375
Stefan Holmer9416ef82018-07-19 10:34:38 +0200376bool RtpVideoSender::IsActive() {
Tommi97888bd2016-01-21 23:24:59 +0100377 rtc::CritScope lock(&crit_);
Niels Möller5fe95102019-03-04 16:49:25 +0100378 return active_ && !rtp_streams_.empty();
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000379}
380
Stefan Holmer9416ef82018-07-19 10:34:38 +0200381EncodedImageCallback::Result RtpVideoSender::OnEncodedImage(
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700382 const EncodedImage& encoded_image,
383 const CodecSpecificInfo* codec_specific_info,
384 const RTPFragmentationHeader* fragmentation) {
Niels Möller77536a22019-01-15 08:50:01 +0100385 fec_controller_->UpdateWithEncodedData(encoded_image.size(),
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200386 encoded_image._frameType);
Tommi97888bd2016-01-21 23:24:59 +0100387 rtc::CritScope lock(&crit_);
Niels Möller5fe95102019-03-04 16:49:25 +0100388 RTC_DCHECK(!rtp_streams_.empty());
Per512ecb32016-09-23 15:52:06 +0200389 if (!active_)
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700390 return Result(Result::ERROR_SEND_FAILED);
mflodman@webrtc.org50e28162015-02-23 07:45:11 +0000391
philipelbf2b6202018-08-27 14:33:18 +0200392 shared_frame_id_++;
Niels Möllerd3b8c632018-08-27 15:33:42 +0200393 size_t stream_index = 0;
394 if (codec_specific_info &&
395 (codec_specific_info->codecType == kVideoCodecVP8 ||
396 codec_specific_info->codecType == kVideoCodecH264 ||
397 codec_specific_info->codecType == kVideoCodecGeneric)) {
398 // Map spatial index to simulcast.
399 stream_index = encoded_image.SpatialIndex().value_or(0);
400 }
Niels Möller5fe95102019-03-04 16:49:25 +0100401 RTC_DCHECK_LT(stream_index, rtp_streams_.size());
Stefan Holmerf7044682018-07-17 10:16:41 +0200402 RTPVideoHeader rtp_video_header = params_[stream_index].GetRtpVideoHeader(
philipelbf2b6202018-08-27 14:33:18 +0200403 encoded_image, codec_specific_info, shared_frame_id_);
Niels Möllerbb894ff2018-03-15 12:28:53 +0100404
Niels Möller5fe95102019-03-04 16:49:25 +0100405 uint32_t rtp_timestamp =
406 encoded_image.Timestamp() +
407 rtp_streams_[stream_index].rtp_rtcp->StartTimestamp();
408
409 // RTCPSender has it's own copy of the timestamp offset, added in
410 // RTCPSender::BuildSR, hence we must not add the in the offset for this call.
411 // TODO(nisse): Delete RTCPSender:timestamp_offset_, and see if we can confine
412 // knowledge of the offset to a single place.
413 if (!rtp_streams_[stream_index].rtp_rtcp->OnSendingRtpFrame(
414 encoded_image.Timestamp(), encoded_image.capture_time_ms_,
415 rtp_config_.payload_type,
Niels Möller8f7ce222019-03-21 15:43:58 +0100416 encoded_image._frameType == VideoFrameType::kVideoFrameKey)) {
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800417 // The payload router could be active but this module isn't sending.
418 return Result(Result::ERROR_SEND_FAILED);
419 }
Niels Möller5fe95102019-03-04 16:49:25 +0100420 int64_t expected_retransmission_time_ms =
421 rtp_streams_[stream_index].rtp_rtcp->ExpectedRetransmissionTimeMs();
Niels Möller949f0fd2019-01-29 09:44:24 +0100422
Niels Möller5fe95102019-03-04 16:49:25 +0100423 bool send_result = rtp_streams_[stream_index].sender_video->SendVideo(
424 encoded_image._frameType, rtp_config_.payload_type, rtp_timestamp,
425 encoded_image.capture_time_ms_, encoded_image.data(),
426 encoded_image.size(), fragmentation, &rtp_video_header,
427 expected_retransmission_time_ms);
Niels Möller949f0fd2019-01-29 09:44:24 +0100428 if (frame_count_observer_) {
429 FrameCounts& counts = frame_counts_[stream_index];
Niels Möller8f7ce222019-03-21 15:43:58 +0100430 if (encoded_image._frameType == VideoFrameType::kVideoFrameKey) {
Niels Möller949f0fd2019-01-29 09:44:24 +0100431 ++counts.key_frames;
Niels Möller8f7ce222019-03-21 15:43:58 +0100432 } else if (encoded_image._frameType == VideoFrameType::kVideoFrameDelta) {
Niels Möller949f0fd2019-01-29 09:44:24 +0100433 ++counts.delta_frames;
434 } else {
Niels Möller8f7ce222019-03-21 15:43:58 +0100435 RTC_DCHECK(encoded_image._frameType == VideoFrameType::kEmptyFrame);
Niels Möller949f0fd2019-01-29 09:44:24 +0100436 }
437 frame_count_observer_->FrameCountUpdated(counts,
438 rtp_config_.ssrcs[stream_index]);
439 }
sergeyu7b9feee2016-11-17 16:16:14 -0800440 if (!send_result)
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700441 return Result(Result::ERROR_SEND_FAILED);
442
Niels Möller5fe95102019-03-04 16:49:25 +0100443 return Result(Result::OK, rtp_timestamp);
mflodman@webrtc.orga4ef2ce2015-02-12 09:54:18 +0000444}
445
Stefan Holmer9416ef82018-07-19 10:34:38 +0200446void RtpVideoSender::OnBitrateAllocationUpdated(
Erik Språng566124a2018-04-23 12:32:22 +0200447 const VideoBitrateAllocation& bitrate) {
sprang1a646ee2016-12-01 06:34:11 -0800448 rtc::CritScope lock(&crit_);
449 if (IsActive()) {
Oleh Prypine8964902019-03-29 15:33:01 +0000450 if (rtp_streams_.size() == 1) {
sprang1a646ee2016-12-01 06:34:11 -0800451 // If spatial scalability is enabled, it is covered by a single stream.
Niels Möller5fe95102019-03-04 16:49:25 +0100452 rtp_streams_[0].rtp_rtcp->SetVideoBitrateAllocation(bitrate);
sprang1a646ee2016-12-01 06:34:11 -0800453 } else {
Stefan Holmerf7044682018-07-17 10:16:41 +0200454 std::vector<absl::optional<VideoBitrateAllocation>> layer_bitrates =
455 bitrate.GetSimulcastAllocations();
Erik Språng566124a2018-04-23 12:32:22 +0200456 // Simulcast is in use, split the VideoBitrateAllocation into one struct
457 // per rtp stream, moving over the temporal layer allocation.
Niels Möller5fe95102019-03-04 16:49:25 +0100458 for (size_t i = 0; i < rtp_streams_.size(); ++i) {
Stefan Holmerf7044682018-07-17 10:16:41 +0200459 // The next spatial layer could be used if the current one is
460 // inactive.
461 if (layer_bitrates[i]) {
Niels Möller5fe95102019-03-04 16:49:25 +0100462 rtp_streams_[i].rtp_rtcp->SetVideoBitrateAllocation(
463 *layer_bitrates[i]);
Ilya Nikolaevskiyb0588e62018-08-27 14:12:27 +0200464 } else {
465 // Signal a 0 bitrate on a simulcast stream.
Niels Möller5fe95102019-03-04 16:49:25 +0100466 rtp_streams_[i].rtp_rtcp->SetVideoBitrateAllocation(
467 VideoBitrateAllocation());
Seth Hampson46e31ba2018-01-18 10:39:54 -0800468 }
sprang1a646ee2016-12-01 06:34:11 -0800469 }
470 }
471 }
472}
473
Stefan Holmer9416ef82018-07-19 10:34:38 +0200474void RtpVideoSender::ConfigureProtection(const RtpConfig& rtp_config) {
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200475 // Consistency of FlexFEC parameters is checked in MaybeCreateFlexfecSender.
476 const bool flexfec_enabled = (flexfec_sender_ != nullptr);
477
478 // Consistency of NACK and RED+ULPFEC parameters is checked in this function.
479 const bool nack_enabled = rtp_config.nack.rtp_history_ms > 0;
480 int red_payload_type = rtp_config.ulpfec.red_payload_type;
481 int ulpfec_payload_type = rtp_config.ulpfec.ulpfec_payload_type;
482
483 // Shorthands.
484 auto IsRedEnabled = [&]() { return red_payload_type >= 0; };
485 auto IsUlpfecEnabled = [&]() { return ulpfec_payload_type >= 0; };
486 auto DisableRedAndUlpfec = [&]() {
487 red_payload_type = -1;
488 ulpfec_payload_type = -1;
489 };
490
491 if (webrtc::field_trial::IsEnabled("WebRTC-DisableUlpFecExperiment")) {
492 RTC_LOG(LS_INFO) << "Experiment to disable sending ULPFEC is enabled.";
493 DisableRedAndUlpfec();
494 }
495
496 // If enabled, FlexFEC takes priority over RED+ULPFEC.
497 if (flexfec_enabled) {
498 if (IsUlpfecEnabled()) {
499 RTC_LOG(LS_INFO)
500 << "Both FlexFEC and ULPFEC are configured. Disabling ULPFEC.";
501 }
502 DisableRedAndUlpfec();
503 }
504
505 // Payload types without picture ID cannot determine that a stream is complete
506 // without retransmitting FEC, so using ULPFEC + NACK for H.264 (for instance)
507 // is a waste of bandwidth since FEC packets still have to be transmitted.
508 // Note that this is not the case with FlexFEC.
509 if (nack_enabled && IsUlpfecEnabled() &&
510 !PayloadTypeSupportsSkippingFecPackets(rtp_config.payload_name)) {
511 RTC_LOG(LS_WARNING)
512 << "Transmitting payload type without picture ID using "
513 "NACK+ULPFEC is a waste of bandwidth since ULPFEC packets "
514 "also have to be retransmitted. Disabling ULPFEC.";
515 DisableRedAndUlpfec();
516 }
517
518 // Verify payload types.
519 if (IsUlpfecEnabled() ^ IsRedEnabled()) {
520 RTC_LOG(LS_WARNING)
521 << "Only RED or only ULPFEC enabled, but not both. Disabling both.";
522 DisableRedAndUlpfec();
523 }
524
Niels Möller5fe95102019-03-04 16:49:25 +0100525 for (const RtpStreamSender& stream : rtp_streams_) {
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200526 // Set NACK.
Niels Möller5fe95102019-03-04 16:49:25 +0100527 stream.rtp_rtcp->SetStorePacketsStatus(true, kMinSendSidePacketHistorySize);
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200528 // Set RED/ULPFEC information.
Niels Möller5fe95102019-03-04 16:49:25 +0100529 stream.sender_video->SetUlpfecConfig(red_payload_type, ulpfec_payload_type);
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200530 }
531}
532
Stefan Holmer9416ef82018-07-19 10:34:38 +0200533bool RtpVideoSender::FecEnabled() const {
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200534 const bool flexfec_enabled = (flexfec_sender_ != nullptr);
Emircan Uysalera7af0212018-09-22 19:11:29 -0400535 const bool ulpfec_enabled =
536 !webrtc::field_trial::IsEnabled("WebRTC-DisableUlpFecExperiment") &&
537 (rtp_config_.ulpfec.ulpfec_payload_type >= 0);
538 return flexfec_enabled || ulpfec_enabled;
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200539}
540
Stefan Holmer9416ef82018-07-19 10:34:38 +0200541bool RtpVideoSender::NackEnabled() const {
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200542 const bool nack_enabled = rtp_config_.nack.rtp_history_ms > 0;
543 return nack_enabled;
544}
545
Erik Språng482b3ef2019-01-08 16:19:11 +0100546uint32_t RtpVideoSender::GetPacketizationOverheadRate() const {
547 uint32_t packetization_overhead_bps = 0;
Niels Möller5fe95102019-03-04 16:49:25 +0100548 for (size_t i = 0; i < rtp_streams_.size(); ++i) {
549 if (rtp_streams_[i].rtp_rtcp->SendingMedia()) {
550 packetization_overhead_bps +=
551 rtp_streams_[i].sender_video->PacketizationOverheadBps();
Erik Språng482b3ef2019-01-08 16:19:11 +0100552 }
553 }
554 return packetization_overhead_bps;
555}
556
Stefan Holmer9416ef82018-07-19 10:34:38 +0200557void RtpVideoSender::DeliverRtcp(const uint8_t* packet, size_t length) {
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200558 // Runs on a network thread.
Niels Möller5fe95102019-03-04 16:49:25 +0100559 for (const RtpStreamSender& stream : rtp_streams_)
560 stream.rtp_rtcp->IncomingRtcpPacket(packet, length);
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200561}
562
Stefan Holmer9416ef82018-07-19 10:34:38 +0200563void RtpVideoSender::ConfigureSsrcs(const RtpConfig& rtp_config) {
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200564 // Configure regular SSRCs.
565 for (size_t i = 0; i < rtp_config.ssrcs.size(); ++i) {
566 uint32_t ssrc = rtp_config.ssrcs[i];
Niels Möller5fe95102019-03-04 16:49:25 +0100567 RtpRtcp* const rtp_rtcp = rtp_streams_[i].rtp_rtcp.get();
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200568 rtp_rtcp->SetSSRC(ssrc);
569
570 // Restore RTP state if previous existed.
571 auto it = suspended_ssrcs_.find(ssrc);
572 if (it != suspended_ssrcs_.end())
573 rtp_rtcp->SetRtpState(it->second);
574 }
575
576 // Set up RTX if available.
577 if (rtp_config.rtx.ssrcs.empty())
578 return;
579
580 // Configure RTX SSRCs.
581 RTC_DCHECK_EQ(rtp_config.rtx.ssrcs.size(), rtp_config.ssrcs.size());
582 for (size_t i = 0; i < rtp_config.rtx.ssrcs.size(); ++i) {
583 uint32_t ssrc = rtp_config.rtx.ssrcs[i];
Niels Möller5fe95102019-03-04 16:49:25 +0100584 RtpRtcp* const rtp_rtcp = rtp_streams_[i].rtp_rtcp.get();
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200585 rtp_rtcp->SetRtxSsrc(ssrc);
586 auto it = suspended_ssrcs_.find(ssrc);
587 if (it != suspended_ssrcs_.end())
588 rtp_rtcp->SetRtxState(it->second);
589 }
590
591 // Configure RTX payload types.
592 RTC_DCHECK_GE(rtp_config.rtx.payload_type, 0);
Niels Möller5fe95102019-03-04 16:49:25 +0100593 for (const RtpStreamSender& stream : rtp_streams_) {
594 stream.rtp_rtcp->SetRtxSendPayloadType(rtp_config.rtx.payload_type,
595 rtp_config.payload_type);
596 stream.rtp_rtcp->SetRtxSendStatus(kRtxRetransmitted |
597 kRtxRedundantPayloads);
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200598 }
599 if (rtp_config.ulpfec.red_payload_type != -1 &&
600 rtp_config.ulpfec.red_rtx_payload_type != -1) {
Niels Möller5fe95102019-03-04 16:49:25 +0100601 for (const RtpStreamSender& stream : rtp_streams_) {
602 stream.rtp_rtcp->SetRtxSendPayloadType(
603 rtp_config.ulpfec.red_rtx_payload_type,
604 rtp_config.ulpfec.red_payload_type);
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200605 }
606 }
607}
608
Amit Hilbuch77938e62018-12-21 09:23:38 -0800609void RtpVideoSender::ConfigureRids(const RtpConfig& rtp_config) {
610 RTC_DCHECK(rtp_config.rids.empty() ||
611 rtp_config.rids.size() == rtp_config.ssrcs.size());
612 RTC_DCHECK(rtp_config.rids.empty() ||
Niels Möller5fe95102019-03-04 16:49:25 +0100613 rtp_config.rids.size() == rtp_streams_.size());
Amit Hilbuch77938e62018-12-21 09:23:38 -0800614 for (size_t i = 0; i < rtp_config.rids.size(); ++i) {
615 const std::string& rid = rtp_config.rids[i];
Niels Möller5fe95102019-03-04 16:49:25 +0100616 rtp_streams_[i].rtp_rtcp->SetRid(rid);
Amit Hilbuch77938e62018-12-21 09:23:38 -0800617 }
618}
619
Stefan Holmer9416ef82018-07-19 10:34:38 +0200620void RtpVideoSender::OnNetworkAvailability(bool network_available) {
Niels Möller5fe95102019-03-04 16:49:25 +0100621 for (const RtpStreamSender& stream : rtp_streams_) {
622 stream.rtp_rtcp->SetRTCPStatus(network_available ? rtp_config_.rtcp_mode
623 : RtcpMode::kOff);
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200624 }
625}
626
Stefan Holmer9416ef82018-07-19 10:34:38 +0200627std::map<uint32_t, RtpState> RtpVideoSender::GetRtpStates() const {
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200628 std::map<uint32_t, RtpState> rtp_states;
629
630 for (size_t i = 0; i < rtp_config_.ssrcs.size(); ++i) {
631 uint32_t ssrc = rtp_config_.ssrcs[i];
Niels Möller5fe95102019-03-04 16:49:25 +0100632 RTC_DCHECK_EQ(ssrc, rtp_streams_[i].rtp_rtcp->SSRC());
633 rtp_states[ssrc] = rtp_streams_[i].rtp_rtcp->GetRtpState();
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200634 }
635
636 for (size_t i = 0; i < rtp_config_.rtx.ssrcs.size(); ++i) {
637 uint32_t ssrc = rtp_config_.rtx.ssrcs[i];
Niels Möller5fe95102019-03-04 16:49:25 +0100638 rtp_states[ssrc] = rtp_streams_[i].rtp_rtcp->GetRtxState();
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200639 }
640
641 if (flexfec_sender_) {
642 uint32_t ssrc = rtp_config_.flexfec.ssrc;
643 rtp_states[ssrc] = flexfec_sender_->GetRtpState();
644 }
645
646 return rtp_states;
647}
648
Stefan Holmer9416ef82018-07-19 10:34:38 +0200649std::map<uint32_t, RtpPayloadState> RtpVideoSender::GetRtpPayloadStates()
650 const {
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200651 rtc::CritScope lock(&crit_);
652 std::map<uint32_t, RtpPayloadState> payload_states;
653 for (const auto& param : params_) {
654 payload_states[param.ssrc()] = param.state();
philipel25d31ec2018-08-08 16:33:01 +0200655 payload_states[param.ssrc()].shared_frame_id = shared_frame_id_;
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200656 }
657 return payload_states;
658}
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200659
660void RtpVideoSender::OnTransportOverheadChanged(
661 size_t transport_overhead_bytes_per_packet) {
662 rtc::CritScope lock(&crit_);
663 transport_overhead_bytes_per_packet_ = transport_overhead_bytes_per_packet;
664
665 size_t max_rtp_packet_size =
666 std::min(rtp_config_.max_packet_size,
667 kPathMTU - transport_overhead_bytes_per_packet_);
Niels Möller5fe95102019-03-04 16:49:25 +0100668 for (const RtpStreamSender& stream : rtp_streams_) {
669 stream.rtp_rtcp->SetMaxRtpPacketSize(max_rtp_packet_size);
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200670 }
671}
672
673void RtpVideoSender::OnOverheadChanged(size_t overhead_bytes_per_packet) {
674 rtc::CritScope lock(&crit_);
675 overhead_bytes_per_packet_ = overhead_bytes_per_packet;
676}
677
678void RtpVideoSender::OnBitrateUpdated(uint32_t bitrate_bps,
679 uint8_t fraction_loss,
680 int64_t rtt,
681 int framerate) {
682 // Substract overhead from bitrate.
683 rtc::CritScope lock(&crit_);
684 uint32_t payload_bitrate_bps = bitrate_bps;
685 if (send_side_bwe_with_overhead_) {
Bjorn Terelius25068392018-10-25 11:07:29 +0200686 uint32_t overhead_bps = CalculateOverheadRateBps(
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200687 CalculatePacketRate(
688 bitrate_bps,
689 rtp_config_.max_packet_size + transport_overhead_bytes_per_packet_),
690 overhead_bytes_per_packet_ + transport_overhead_bytes_per_packet_,
691 bitrate_bps);
Bjorn Terelius25068392018-10-25 11:07:29 +0200692 RTC_DCHECK_LE(overhead_bps, bitrate_bps);
693 payload_bitrate_bps = bitrate_bps - overhead_bps;
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200694 }
695
696 // Get the encoder target rate. It is the estimated network rate -
697 // protection overhead.
698 encoder_target_rate_bps_ = fec_controller_->UpdateFecRates(
699 payload_bitrate_bps, framerate, fraction_loss, loss_mask_vector_, rtt);
Erik Språng482b3ef2019-01-08 16:19:11 +0100700
Erik Språngd15687d2019-01-18 10:47:07 +0100701 uint32_t packetization_rate_bps = 0;
Erik Språngc12d41b2019-01-09 09:55:31 +0100702 if (account_for_packetization_overhead_) {
Erik Språngd15687d2019-01-18 10:47:07 +0100703 // Subtract packetization overhead from the encoder target. If target rate
704 // is really low, cap the overhead at 50%. This also avoids the case where
705 // |encoder_target_rate_bps_| is 0 due to encoder pause event while the
706 // packetization rate is positive since packets are still flowing.
707 packetization_rate_bps =
708 std::min(GetPacketizationOverheadRate(), encoder_target_rate_bps_ / 2);
709 encoder_target_rate_bps_ -= packetization_rate_bps;
Erik Språngc12d41b2019-01-09 09:55:31 +0100710 }
Erik Språng482b3ef2019-01-08 16:19:11 +0100711
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200712 loss_mask_vector_.clear();
713
714 uint32_t encoder_overhead_rate_bps =
715 send_side_bwe_with_overhead_
716 ? CalculateOverheadRateBps(
717 CalculatePacketRate(encoder_target_rate_bps_,
718 rtp_config_.max_packet_size +
719 transport_overhead_bytes_per_packet_ -
720 overhead_bytes_per_packet_),
721 overhead_bytes_per_packet_ +
722 transport_overhead_bytes_per_packet_,
723 bitrate_bps - encoder_target_rate_bps_)
724 : 0;
725
726 // When the field trial "WebRTC-SendSideBwe-WithOverhead" is enabled
727 // protection_bitrate includes overhead.
Erik Språngd15687d2019-01-18 10:47:07 +0100728 const uint32_t media_rate = encoder_target_rate_bps_ +
729 encoder_overhead_rate_bps +
730 packetization_rate_bps;
731 RTC_DCHECK_GE(bitrate_bps, media_rate);
732 protection_bitrate_bps_ = bitrate_bps - media_rate;
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200733}
734
735uint32_t RtpVideoSender::GetPayloadBitrateBps() const {
736 return encoder_target_rate_bps_;
737}
738
739uint32_t RtpVideoSender::GetProtectionBitrateBps() const {
740 return protection_bitrate_bps_;
741}
742
Elad Alon8b60e8b2019-04-08 14:14:05 +0200743absl::optional<RtpSequenceNumberMap::Info> RtpVideoSender::GetSentRtpPacketInfo(
744 uint32_t ssrc,
745 uint16_t seq_num) const {
746 for (const auto& rtp_stream : rtp_streams_) {
747 if (ssrc == rtp_stream.rtp_rtcp->SSRC()) {
748 return rtp_stream.sender_video->GetSentRtpPacketInfo(seq_num);
749 }
750 }
751 return absl::nullopt;
752}
753
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200754int RtpVideoSender::ProtectionRequest(const FecProtectionParams* delta_params,
755 const FecProtectionParams* key_params,
756 uint32_t* sent_video_rate_bps,
757 uint32_t* sent_nack_rate_bps,
758 uint32_t* sent_fec_rate_bps) {
759 *sent_video_rate_bps = 0;
760 *sent_nack_rate_bps = 0;
761 *sent_fec_rate_bps = 0;
Niels Möller5fe95102019-03-04 16:49:25 +0100762 for (const RtpStreamSender& stream : rtp_streams_) {
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200763 uint32_t not_used = 0;
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200764 uint32_t module_nack_rate = 0;
Niels Möller5fe95102019-03-04 16:49:25 +0100765 stream.sender_video->SetFecParameters(*delta_params, *key_params);
766 *sent_video_rate_bps += stream.sender_video->VideoBitrateSent();
767 *sent_fec_rate_bps += stream.sender_video->FecOverheadRate();
768 stream.rtp_rtcp->BitrateSent(&not_used, /*video_rate=*/nullptr,
769 /*fec_rate=*/nullptr, &module_nack_rate);
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200770 *sent_nack_rate_bps += module_nack_rate;
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200771 }
772 return 0;
773}
774
775void RtpVideoSender::OnPacketAdded(uint32_t ssrc, uint16_t seq_num) {
776 const auto ssrcs = rtp_config_.ssrcs;
777 if (std::find(ssrcs.begin(), ssrcs.end(), ssrc) != ssrcs.end()) {
778 feedback_packet_seq_num_set_.insert(seq_num);
779 if (feedback_packet_seq_num_set_.size() > kSendSideSeqNumSetMaxSize) {
780 RTC_LOG(LS_WARNING) << "Feedback packet sequence number set exceed it's "
781 "max size', will get reset.";
782 feedback_packet_seq_num_set_.clear();
783 }
784 }
785}
786
787void RtpVideoSender::OnPacketFeedbackVector(
788 const std::vector<PacketFeedback>& packet_feedback_vector) {
789 rtc::CritScope lock(&crit_);
790 // Lost feedbacks are not considered to be lost packets.
791 for (const PacketFeedback& packet : packet_feedback_vector) {
792 auto it = feedback_packet_seq_num_set_.find(packet.sequence_number);
793 if (it != feedback_packet_seq_num_set_.end()) {
794 const bool lost = packet.arrival_time_ms == PacketFeedback::kNotReceived;
795 loss_mask_vector_.push_back(lost);
796 feedback_packet_seq_num_set_.erase(it);
797 }
798 }
799}
800
801void RtpVideoSender::SetEncodingData(size_t width,
802 size_t height,
803 size_t num_temporal_layers) {
804 fec_controller_->SetEncodingData(width, height, num_temporal_layers,
805 rtp_config_.max_packet_size);
806}
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000807} // namespace webrtc