blob: 3ca1da3bd91797e5266246a1c1dad650a8cb83c0 [file] [log] [blame]
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +02001/*
2 * Copyright 2018 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#include "video/video_send_stream_impl.h"
11
12#include <algorithm>
13#include <string>
14#include <utility>
15
16#include "call/rtp_transport_controller_send_interface.h"
17#include "modules/pacing/packet_router.h"
18#include "modules/rtp_rtcp/include/rtp_rtcp.h"
19#include "modules/rtp_rtcp/source/rtp_sender.h"
20#include "rtc_base/checks.h"
21#include "rtc_base/experiments/alr_experiment.h"
22#include "rtc_base/file.h"
23#include "rtc_base/location.h"
24#include "rtc_base/logging.h"
25#include "rtc_base/numerics/safe_conversions.h"
26#include "rtc_base/trace_event.h"
27#include "system_wrappers/include/field_trial.h"
28
29namespace webrtc {
30namespace internal {
31namespace {
32static const int kMinSendSidePacketHistorySize = 600;
33
34// 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
39// We don't do MTU discovery, so assume that we have the standard ethernet MTU.
40const size_t kPathMTU = 1500;
41
42std::vector<RtpRtcp*> CreateRtpRtcpModules(
43 const VideoSendStream::Config& config,
44 RtcpIntraFrameObserver* intra_frame_callback,
45 RtcpBandwidthObserver* bandwidth_callback,
46 RtpTransportControllerSendInterface* transport,
47 RtcpRttStats* rtt_stats,
48 FlexfecSender* flexfec_sender,
49 SendStatisticsProxy* stats_proxy,
50 SendDelayStats* send_delay_stats,
51 RtcEventLog* event_log,
52 RateLimiter* retransmission_rate_limiter,
53 OverheadObserver* overhead_observer,
54 RtpKeepAliveConfig keepalive_config) {
55 RTC_DCHECK_GT(config.rtp.ssrcs.size(), 0);
56 RtpRtcp::Configuration configuration;
57 configuration.audio = false;
58 configuration.receiver_only = false;
59 configuration.outgoing_transport = config.send_transport;
60 configuration.intra_frame_callback = intra_frame_callback;
61 configuration.bandwidth_callback = bandwidth_callback;
62 configuration.transport_feedback_callback =
63 transport->transport_feedback_observer();
64 configuration.rtt_stats = rtt_stats;
65 configuration.rtcp_packet_type_counter_observer = stats_proxy;
66 configuration.paced_sender = transport->packet_sender();
67 configuration.transport_sequence_number_allocator =
68 transport->packet_router();
69 configuration.send_bitrate_observer = stats_proxy;
70 configuration.send_frame_count_observer = stats_proxy;
71 configuration.send_side_delay_observer = stats_proxy;
72 configuration.send_packet_observer = send_delay_stats;
73 configuration.event_log = event_log;
74 configuration.retransmission_rate_limiter = retransmission_rate_limiter;
75 configuration.overhead_observer = overhead_observer;
76 configuration.keepalive_config = keepalive_config;
77 configuration.rtcp_interval_config.video_interval_ms =
78 config.rtcp.video_report_interval_ms;
79 configuration.rtcp_interval_config.audio_interval_ms =
80 config.rtcp.audio_report_interval_ms;
81 std::vector<RtpRtcp*> modules;
82 const std::vector<uint32_t>& flexfec_protected_ssrcs =
83 config.rtp.flexfec.protected_media_ssrcs;
84 for (uint32_t ssrc : config.rtp.ssrcs) {
85 bool enable_flexfec = flexfec_sender != nullptr &&
86 std::find(flexfec_protected_ssrcs.begin(),
87 flexfec_protected_ssrcs.end(),
88 ssrc) != flexfec_protected_ssrcs.end();
89 configuration.flexfec_sender = enable_flexfec ? flexfec_sender : nullptr;
90 RtpRtcp* rtp_rtcp = RtpRtcp::CreateRtpRtcp(configuration);
91 rtp_rtcp->SetSendingStatus(false);
92 rtp_rtcp->SetSendingMediaStatus(false);
93 rtp_rtcp->SetRTCPStatus(RtcpMode::kCompound);
94 modules.push_back(rtp_rtcp);
95 }
96 return modules;
97}
98
99// TODO(brandtr): Update this function when we support multistream protection.
100std::unique_ptr<FlexfecSender> MaybeCreateFlexfecSender(
101 const VideoSendStream::Config& config,
102 const std::map<uint32_t, RtpState>& suspended_ssrcs) {
103 if (config.rtp.flexfec.payload_type < 0) {
104 return nullptr;
105 }
106 RTC_DCHECK_GE(config.rtp.flexfec.payload_type, 0);
107 RTC_DCHECK_LE(config.rtp.flexfec.payload_type, 127);
108 if (config.rtp.flexfec.ssrc == 0) {
109 RTC_LOG(LS_WARNING) << "FlexFEC is enabled, but no FlexFEC SSRC given. "
110 "Therefore disabling FlexFEC.";
111 return nullptr;
112 }
113 if (config.rtp.flexfec.protected_media_ssrcs.empty()) {
114 RTC_LOG(LS_WARNING)
115 << "FlexFEC is enabled, but no protected media SSRC given. "
116 "Therefore disabling FlexFEC.";
117 return nullptr;
118 }
119
120 if (config.rtp.flexfec.protected_media_ssrcs.size() > 1) {
121 RTC_LOG(LS_WARNING)
122 << "The supplied FlexfecConfig contained multiple protected "
123 "media streams, but our implementation currently only "
124 "supports protecting a single media stream. "
125 "To avoid confusion, disabling FlexFEC completely.";
126 return nullptr;
127 }
128
129 const RtpState* rtp_state = nullptr;
130 auto it = suspended_ssrcs.find(config.rtp.flexfec.ssrc);
131 if (it != suspended_ssrcs.end()) {
132 rtp_state = &it->second;
133 }
134
135 RTC_DCHECK_EQ(1U, config.rtp.flexfec.protected_media_ssrcs.size());
Karl Wiberg918f50c2018-07-05 11:40:33 +0200136 return absl::make_unique<FlexfecSender>(
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200137 config.rtp.flexfec.payload_type, config.rtp.flexfec.ssrc,
138 config.rtp.flexfec.protected_media_ssrcs[0], config.rtp.mid,
139 config.rtp.extensions, RTPSender::FecExtensionSizes(), rtp_state,
140 Clock::GetRealTimeClock());
141}
142
143bool TransportSeqNumExtensionConfigured(const VideoSendStream::Config& config) {
144 const std::vector<RtpExtension>& extensions = config.rtp.extensions;
145 return std::find_if(
146 extensions.begin(), extensions.end(), [](const RtpExtension& ext) {
147 return ext.uri == RtpExtension::kTransportSequenceNumberUri;
148 }) != extensions.end();
149}
150
151const char kForcedFallbackFieldTrial[] =
152 "WebRTC-VP8-Forced-Fallback-Encoder-v2";
153
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200154absl::optional<int> GetFallbackMinBpsFromFieldTrial() {
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200155 if (!webrtc::field_trial::IsEnabled(kForcedFallbackFieldTrial))
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200156 return absl::nullopt;
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200157
158 std::string group =
159 webrtc::field_trial::FindFullName(kForcedFallbackFieldTrial);
160 if (group.empty())
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200161 return absl::nullopt;
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200162
163 int min_pixels;
164 int max_pixels;
165 int min_bps;
166 if (sscanf(group.c_str(), "Enabled-%d,%d,%d", &min_pixels, &max_pixels,
167 &min_bps) != 3) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200168 return absl::nullopt;
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200169 }
170
171 if (min_bps <= 0)
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200172 return absl::nullopt;
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200173
174 return min_bps;
175}
176
177int GetEncoderMinBitrateBps() {
178 const int kDefaultEncoderMinBitrateBps = 30000;
179 return GetFallbackMinBpsFromFieldTrial().value_or(
180 kDefaultEncoderMinBitrateBps);
181}
182
183bool PayloadTypeSupportsSkippingFecPackets(const std::string& payload_name) {
184 const VideoCodecType codecType = PayloadStringToCodecType(payload_name);
185 if (codecType == kVideoCodecVP8 || codecType == kVideoCodecVP9) {
186 return true;
187 }
188 return false;
189}
190
191int CalculateMaxPadBitrateBps(std::vector<VideoStream> streams,
192 int min_transmit_bitrate_bps,
193 bool pad_to_min_bitrate) {
194 int pad_up_to_bitrate_bps = 0;
195 // Calculate max padding bitrate for a multi layer codec.
196 if (streams.size() > 1) {
197 // Pad to min bitrate of the highest layer.
198 pad_up_to_bitrate_bps = streams[streams.size() - 1].min_bitrate_bps;
199 // Add target_bitrate_bps of the lower layers.
200 for (size_t i = 0; i < streams.size() - 1; ++i)
201 pad_up_to_bitrate_bps += streams[i].target_bitrate_bps;
202 } else if (pad_to_min_bitrate) {
203 pad_up_to_bitrate_bps = streams[0].min_bitrate_bps;
204 }
205
206 pad_up_to_bitrate_bps =
207 std::max(pad_up_to_bitrate_bps, min_transmit_bitrate_bps);
208
209 return pad_up_to_bitrate_bps;
210}
211
212uint32_t CalculateOverheadRateBps(int packets_per_second,
213 size_t overhead_bytes_per_packet,
214 uint32_t max_overhead_bps) {
215 uint32_t overhead_bps =
216 static_cast<uint32_t>(8 * overhead_bytes_per_packet * packets_per_second);
217 return std::min(overhead_bps, max_overhead_bps);
218}
219
220int CalculatePacketRate(uint32_t bitrate_bps, size_t packet_size_bytes) {
221 size_t packet_size_bits = 8 * packet_size_bytes;
222 // Ceil for int value of bitrate_bps / packet_size_bits.
223 return static_cast<int>((bitrate_bps + packet_size_bits - 1) /
224 packet_size_bits);
225}
226
227} // namespace
228
229// CheckEncoderActivityTask is used for tracking when the encoder last produced
230// and encoded video frame. If the encoder has not produced anything the last
231// kEncoderTimeOutMs we also want to stop sending padding.
232class VideoSendStreamImpl::CheckEncoderActivityTask : public rtc::QueuedTask {
233 public:
234 static const int kEncoderTimeOutMs = 2000;
235 explicit CheckEncoderActivityTask(
236 const rtc::WeakPtr<VideoSendStreamImpl>& send_stream)
237 : activity_(0), send_stream_(std::move(send_stream)), timed_out_(false) {}
238
239 void Stop() {
240 RTC_CHECK(task_checker_.CalledSequentially());
241 send_stream_.reset();
242 }
243
244 void UpdateEncoderActivity() {
245 // UpdateEncoderActivity is called from VideoSendStreamImpl::Encoded on
246 // whatever thread the real encoder implementation run on. In the case of
247 // hardware encoders, there might be several encoders
248 // running in parallel on different threads.
249 rtc::AtomicOps::ReleaseStore(&activity_, 1);
250 }
251
252 private:
253 bool Run() override {
254 RTC_CHECK(task_checker_.CalledSequentially());
255 if (!send_stream_)
256 return true;
257 if (!rtc::AtomicOps::AcquireLoad(&activity_)) {
258 if (!timed_out_) {
259 send_stream_->SignalEncoderTimedOut();
260 }
261 timed_out_ = true;
262 } else if (timed_out_) {
263 send_stream_->SignalEncoderActive();
264 timed_out_ = false;
265 }
266 rtc::AtomicOps::ReleaseStore(&activity_, 0);
267
268 rtc::TaskQueue::Current()->PostDelayedTask(
269 std::unique_ptr<rtc::QueuedTask>(this), kEncoderTimeOutMs);
270 // Return false to prevent this task from being deleted. Ownership has been
271 // transferred to the task queue when PostDelayedTask was called.
272 return false;
273 }
274 volatile int activity_;
275
276 rtc::SequencedTaskChecker task_checker_;
277 rtc::WeakPtr<VideoSendStreamImpl> send_stream_;
278 bool timed_out_;
279};
280
281VideoSendStreamImpl::VideoSendStreamImpl(
282 SendStatisticsProxy* stats_proxy,
283 rtc::TaskQueue* worker_queue,
284 CallStats* call_stats,
285 RtpTransportControllerSendInterface* transport,
Sebastian Jansson652dc912018-04-19 17:09:15 +0200286 BitrateAllocatorInterface* bitrate_allocator,
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200287 SendDelayStats* send_delay_stats,
Sebastian Jansson652dc912018-04-19 17:09:15 +0200288 VideoStreamEncoderInterface* video_stream_encoder,
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200289 RtcEventLog* event_log,
290 const VideoSendStream::Config* config,
291 int initial_encoder_max_bitrate,
292 double initial_encoder_bitrate_priority,
293 std::map<uint32_t, RtpState> suspended_ssrcs,
294 std::map<uint32_t, RtpPayloadState> suspended_payload_states,
295 VideoEncoderConfig::ContentType content_type,
296 std::unique_ptr<FecController> fec_controller,
297 RateLimiter* retransmission_limiter)
298 : send_side_bwe_with_overhead_(
299 webrtc::field_trial::IsEnabled("WebRTC-SendSideBwe-WithOverhead")),
300 stats_proxy_(stats_proxy),
301 config_(config),
302 suspended_ssrcs_(std::move(suspended_ssrcs)),
303 fec_controller_(std::move(fec_controller)),
304 module_process_thread_(nullptr),
305 worker_queue_(worker_queue),
306 check_encoder_activity_task_(nullptr),
307 call_stats_(call_stats),
308 transport_(transport),
309 bitrate_allocator_(bitrate_allocator),
310 flexfec_sender_(MaybeCreateFlexfecSender(*config_, suspended_ssrcs_)),
311 max_padding_bitrate_(0),
312 encoder_min_bitrate_bps_(0),
313 encoder_target_rate_bps_(0),
314 encoder_bitrate_priority_(initial_encoder_bitrate_priority),
315 has_packet_feedback_(false),
316 video_stream_encoder_(video_stream_encoder),
317 encoder_feedback_(Clock::GetRealTimeClock(),
318 config_->rtp.ssrcs,
319 video_stream_encoder),
320 bandwidth_observer_(transport->GetBandwidthObserver()),
321 rtp_rtcp_modules_(CreateRtpRtcpModules(*config_,
322 &encoder_feedback_,
323 bandwidth_observer_,
324 transport,
325 call_stats,
326 flexfec_sender_.get(),
327 stats_proxy_,
328 send_delay_stats,
329 event_log,
330 retransmission_limiter,
331 this,
332 transport->keepalive_config())),
333 payload_router_(rtp_rtcp_modules_,
334 config_->rtp.ssrcs,
335 config_->rtp.payload_type,
336 suspended_payload_states),
337 weak_ptr_factory_(this),
338 overhead_bytes_per_packet_(0),
339 transport_overhead_bytes_per_packet_(0) {
340 RTC_DCHECK_RUN_ON(worker_queue_);
341 RTC_LOG(LS_INFO) << "VideoSendStreamInternal: " << config_->ToString();
342 weak_ptr_ = weak_ptr_factory_.GetWeakPtr();
343 module_process_thread_checker_.DetachFromThread();
344
345 RTC_DCHECK(!config_->rtp.ssrcs.empty());
346 RTC_DCHECK(call_stats_);
347 RTC_DCHECK(transport_);
348 RTC_DCHECK_NE(initial_encoder_max_bitrate, 0);
349
350 if (initial_encoder_max_bitrate > 0) {
351 encoder_max_bitrate_bps_ =
352 rtc::dchecked_cast<uint32_t>(initial_encoder_max_bitrate);
353 } else {
354 // TODO(srte): Make sure max bitrate is not set to negative values. We don't
355 // have any way to handle unset values in downstream code, such as the
356 // bitrate allocator. Previously -1 was implicitly casted to UINT32_MAX, a
357 // behaviour that is not safe. Converting to 10 Mbps should be safe for
358 // reasonable use cases as it allows adding the max of multiple streams
359 // without wrappping around.
360 const int kFallbackMaxBitrateBps = 10000000;
361 RTC_DLOG(LS_ERROR) << "ERROR: Initial encoder max bitrate = "
362 << initial_encoder_max_bitrate << " which is <= 0!";
363 RTC_DLOG(LS_INFO) << "Using default encoder max bitrate = 10 Mbps";
364 encoder_max_bitrate_bps_ = kFallbackMaxBitrateBps;
365 }
366
367 RTC_CHECK(AlrExperimentSettings::MaxOneFieldTrialEnabled());
368 // If send-side BWE is enabled, check if we should apply updated probing and
369 // pacing settings.
370 if (TransportSeqNumExtensionConfigured(*config_)) {
371 has_packet_feedback_ = true;
372
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200373 absl::optional<AlrExperimentSettings> alr_settings;
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200374 if (content_type == VideoEncoderConfig::ContentType::kScreen) {
375 alr_settings = AlrExperimentSettings::CreateFromFieldTrial(
376 AlrExperimentSettings::kScreenshareProbingBweExperimentName);
377 } else {
378 alr_settings = AlrExperimentSettings::CreateFromFieldTrial(
379 AlrExperimentSettings::kStrictPacingAndProbingExperimentName);
380 }
381 if (alr_settings) {
382 transport->EnablePeriodicAlrProbing(true);
383 transport->SetPacingFactor(alr_settings->pacing_factor);
384 configured_pacing_factor_ = alr_settings->pacing_factor;
385 transport->SetQueueTimeLimit(alr_settings->max_paced_queue_time);
386 } else {
387 transport->EnablePeriodicAlrProbing(false);
388 transport->SetPacingFactor(PacedSender::kDefaultPaceMultiplier);
389 configured_pacing_factor_ = PacedSender::kDefaultPaceMultiplier;
390 transport->SetQueueTimeLimit(PacedSender::kMaxQueueLengthMs);
391 }
392 }
393
394 if (config_->periodic_alr_bandwidth_probing) {
395 transport->EnablePeriodicAlrProbing(true);
396 }
397
398 // RTP/RTCP initialization.
399
400 // We add the highest spatial layer first to ensure it'll be prioritized
401 // when sending padding, with the hope that the packet rate will be smaller,
402 // and that it's more important to protect than the lower layers.
403 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
404 constexpr bool remb_candidate = true;
405 transport->packet_router()->AddSendRtpModule(rtp_rtcp, remb_candidate);
406 }
407
408 for (size_t i = 0; i < config_->rtp.extensions.size(); ++i) {
409 const std::string& extension = config_->rtp.extensions[i].uri;
410 int id = config_->rtp.extensions[i].id;
411 // One-byte-extension local identifiers are in the range 1-14 inclusive.
412 RTC_DCHECK_GE(id, 1);
413 RTC_DCHECK_LE(id, 14);
414 RTC_DCHECK(RtpExtension::IsSupportedForVideo(extension));
415 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
416 RTC_CHECK_EQ(0, rtp_rtcp->RegisterSendRtpHeaderExtension(
417 StringToRtpExtensionType(extension), id));
418 }
419 }
420
421 ConfigureProtection();
422 ConfigureSsrcs();
423
424 if (!config_->rtp.mid.empty()) {
425 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
426 rtp_rtcp->SetMid(config_->rtp.mid);
427 }
428 }
429
430 // TODO(pbos): Should we set CNAME on all RTP modules?
431 rtp_rtcp_modules_.front()->SetCNAME(config_->rtp.c_name.c_str());
432
433 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
434 rtp_rtcp->RegisterRtcpStatisticsCallback(stats_proxy_);
435 rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(stats_proxy_);
436 rtp_rtcp->SetMaxRtpPacketSize(config_->rtp.max_packet_size);
437 rtp_rtcp->RegisterVideoSendPayload(config_->rtp.payload_type,
438 config_->rtp.payload_name.c_str());
439 }
440
441 fec_controller_->SetProtectionCallback(this);
442 // Signal congestion controller this object is ready for OnPacket* callbacks.
443 if (fec_controller_->UseLossVectorMask()) {
444 transport_->RegisterPacketFeedbackObserver(this);
445 }
446
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200447 RTC_DCHECK_GE(config_->rtp.payload_type, 0);
448 RTC_DCHECK_LE(config_->rtp.payload_type, 127);
449
450 video_stream_encoder_->SetStartBitrate(
451 bitrate_allocator_->GetStartBitrate(this));
452
453 // Only request rotation at the source when we positively know that the remote
454 // side doesn't support the rotation extension. This allows us to prepare the
455 // encoder in the expectation that rotation is supported - which is the common
456 // case.
457 bool rotation_applied =
458 std::find_if(config_->rtp.extensions.begin(),
459 config_->rtp.extensions.end(),
460 [](const RtpExtension& extension) {
461 return extension.uri == RtpExtension::kVideoRotationUri;
462 }) == config_->rtp.extensions.end();
463
464 video_stream_encoder_->SetSink(this, rotation_applied);
465}
466
467void VideoSendStreamImpl::RegisterProcessThread(
468 ProcessThread* module_process_thread) {
469 RTC_DCHECK_RUN_ON(&module_process_thread_checker_);
470 RTC_DCHECK(!module_process_thread_);
471 module_process_thread_ = module_process_thread;
472
473 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_)
474 module_process_thread_->RegisterModule(rtp_rtcp, RTC_FROM_HERE);
475}
476
477void VideoSendStreamImpl::DeRegisterProcessThread() {
478 RTC_DCHECK_RUN_ON(&module_process_thread_checker_);
479 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_)
480 module_process_thread_->DeRegisterModule(rtp_rtcp);
481}
482
483VideoSendStreamImpl::~VideoSendStreamImpl() {
484 RTC_DCHECK_RUN_ON(worker_queue_);
485 RTC_DCHECK(!payload_router_.IsActive())
486 << "VideoSendStreamImpl::Stop not called";
487 RTC_LOG(LS_INFO) << "~VideoSendStreamInternal: " << config_->ToString();
488 if (fec_controller_->UseLossVectorMask()) {
489 transport_->DeRegisterPacketFeedbackObserver(this);
490 }
491 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
492 transport_->packet_router()->RemoveSendRtpModule(rtp_rtcp);
493 delete rtp_rtcp;
494 }
495}
496
497bool VideoSendStreamImpl::DeliverRtcp(const uint8_t* packet, size_t length) {
498 // Runs on a network thread.
499 RTC_DCHECK(!worker_queue_->IsCurrent());
500 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_)
501 rtp_rtcp->IncomingRtcpPacket(packet, length);
502 return true;
503}
504
505void VideoSendStreamImpl::UpdateActiveSimulcastLayers(
506 const std::vector<bool> active_layers) {
507 RTC_DCHECK_RUN_ON(worker_queue_);
508 RTC_DCHECK_EQ(rtp_rtcp_modules_.size(), active_layers.size());
509 RTC_LOG(LS_INFO) << "VideoSendStream::UpdateActiveSimulcastLayers";
510 bool previously_active = payload_router_.IsActive();
511 payload_router_.SetActiveModules(active_layers);
512 if (!payload_router_.IsActive() && previously_active) {
513 // Payload router switched from active to inactive.
514 StopVideoSendStream();
515 } else if (payload_router_.IsActive() && !previously_active) {
516 // Payload router switched from inactive to active.
517 StartupVideoSendStream();
518 }
519}
520
521void VideoSendStreamImpl::Start() {
522 RTC_DCHECK_RUN_ON(worker_queue_);
523 RTC_LOG(LS_INFO) << "VideoSendStream::Start";
524 if (payload_router_.IsActive())
525 return;
526 TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Start");
527 payload_router_.SetActive(true);
528 StartupVideoSendStream();
529}
530
531void VideoSendStreamImpl::StartupVideoSendStream() {
532 RTC_DCHECK_RUN_ON(worker_queue_);
533 bitrate_allocator_->AddObserver(
Sebastian Jansson24ad7202018-04-19 08:25:12 +0200534 this,
535 MediaStreamAllocationConfig{
536 static_cast<uint32_t>(encoder_min_bitrate_bps_),
537 encoder_max_bitrate_bps_, static_cast<uint32_t>(max_padding_bitrate_),
538 !config_->suspend_below_min_bitrate, config_->track_id,
539 encoder_bitrate_priority_, has_packet_feedback_});
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200540 // Start monitoring encoder activity.
541 {
542 rtc::CritScope lock(&encoder_activity_crit_sect_);
543 RTC_DCHECK(!check_encoder_activity_task_);
544 check_encoder_activity_task_ = new CheckEncoderActivityTask(weak_ptr_);
545 worker_queue_->PostDelayedTask(
546 std::unique_ptr<rtc::QueuedTask>(check_encoder_activity_task_),
547 CheckEncoderActivityTask::kEncoderTimeOutMs);
548 }
549
550 video_stream_encoder_->SendKeyFrame();
551}
552
553void VideoSendStreamImpl::Stop() {
554 RTC_DCHECK_RUN_ON(worker_queue_);
555 RTC_LOG(LS_INFO) << "VideoSendStream::Stop";
556 if (!payload_router_.IsActive())
557 return;
558 TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Stop");
559 payload_router_.SetActive(false);
560 StopVideoSendStream();
561}
562
563void VideoSendStreamImpl::StopVideoSendStream() {
564 bitrate_allocator_->RemoveObserver(this);
565 {
566 rtc::CritScope lock(&encoder_activity_crit_sect_);
567 check_encoder_activity_task_->Stop();
568 check_encoder_activity_task_ = nullptr;
569 }
570 video_stream_encoder_->OnBitrateUpdated(0, 0, 0);
571 stats_proxy_->OnSetEncoderTargetRate(0);
572}
573
574void VideoSendStreamImpl::SignalEncoderTimedOut() {
575 RTC_DCHECK_RUN_ON(worker_queue_);
576 // If the encoder has not produced anything the last kEncoderTimeOutMs and it
577 // is supposed to, deregister as BitrateAllocatorObserver. This can happen
578 // if a camera stops producing frames.
579 if (encoder_target_rate_bps_ > 0) {
580 RTC_LOG(LS_INFO) << "SignalEncoderTimedOut, Encoder timed out.";
581 bitrate_allocator_->RemoveObserver(this);
582 }
583}
584
585void VideoSendStreamImpl::OnBitrateAllocationUpdated(
Erik Språng566124a2018-04-23 12:32:22 +0200586 const VideoBitrateAllocation& allocation) {
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200587 payload_router_.OnBitrateAllocationUpdated(allocation);
588}
589
590void VideoSendStreamImpl::SignalEncoderActive() {
591 RTC_DCHECK_RUN_ON(worker_queue_);
592 RTC_LOG(LS_INFO) << "SignalEncoderActive, Encoder is active.";
593 bitrate_allocator_->AddObserver(
Sebastian Jansson24ad7202018-04-19 08:25:12 +0200594 this,
595 MediaStreamAllocationConfig{
596 static_cast<uint32_t>(encoder_min_bitrate_bps_),
597 encoder_max_bitrate_bps_, static_cast<uint32_t>(max_padding_bitrate_),
598 !config_->suspend_below_min_bitrate, config_->track_id,
599 encoder_bitrate_priority_, has_packet_feedback_});
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200600}
601
602void VideoSendStreamImpl::OnEncoderConfigurationChanged(
603 std::vector<VideoStream> streams,
604 int min_transmit_bitrate_bps) {
605 if (!worker_queue_->IsCurrent()) {
606 rtc::WeakPtr<VideoSendStreamImpl> send_stream = weak_ptr_;
607 worker_queue_->PostTask([send_stream, streams, min_transmit_bitrate_bps]() {
608 if (send_stream)
609 send_stream->OnEncoderConfigurationChanged(std::move(streams),
610 min_transmit_bitrate_bps);
611 });
612 return;
613 }
614 RTC_DCHECK_GE(config_->rtp.ssrcs.size(), streams.size());
615 TRACE_EVENT0("webrtc", "VideoSendStream::OnEncoderConfigurationChanged");
616 RTC_DCHECK_GE(config_->rtp.ssrcs.size(), streams.size());
617 RTC_DCHECK_RUN_ON(worker_queue_);
618
619 encoder_min_bitrate_bps_ =
620 std::max(streams[0].min_bitrate_bps, GetEncoderMinBitrateBps());
621 encoder_max_bitrate_bps_ = 0;
622 double stream_bitrate_priority_sum = 0;
623 for (const auto& stream : streams) {
624 // We don't want to allocate more bitrate than needed to inactive streams.
625 encoder_max_bitrate_bps_ += stream.active ? stream.max_bitrate_bps : 0;
626 if (stream.bitrate_priority) {
627 RTC_DCHECK_GT(*stream.bitrate_priority, 0);
628 stream_bitrate_priority_sum += *stream.bitrate_priority;
629 }
630 }
631 RTC_DCHECK_GT(stream_bitrate_priority_sum, 0);
632 encoder_bitrate_priority_ = stream_bitrate_priority_sum;
633 encoder_max_bitrate_bps_ =
634 std::max(static_cast<uint32_t>(encoder_min_bitrate_bps_),
635 encoder_max_bitrate_bps_);
“Michael277a6562018-06-01 14:09:19 -0500636
637 const VideoCodecType codec_type =
638 PayloadStringToCodecType(config_->rtp.payload_name);
639 if (codec_type == kVideoCodecVP9) {
640 max_padding_bitrate_ = streams[0].target_bitrate_bps;
641 } else {
642 max_padding_bitrate_ = CalculateMaxPadBitrateBps(
643 streams, min_transmit_bitrate_bps, config_->suspend_below_min_bitrate);
644 }
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200645
646 // Clear stats for disabled layers.
647 for (size_t i = streams.size(); i < config_->rtp.ssrcs.size(); ++i) {
648 stats_proxy_->OnInactiveSsrc(config_->rtp.ssrcs[i]);
649 }
650
651 const size_t num_temporal_layers =
652 streams.back().num_temporal_layers.value_or(1);
653 fec_controller_->SetEncodingData(streams[0].width, streams[0].height,
654 num_temporal_layers,
655 config_->rtp.max_packet_size);
656
657 if (payload_router_.IsActive()) {
658 // The send stream is started already. Update the allocator with new bitrate
659 // limits.
660 bitrate_allocator_->AddObserver(
Sebastian Jansson24ad7202018-04-19 08:25:12 +0200661 this, MediaStreamAllocationConfig{
662 static_cast<uint32_t>(encoder_min_bitrate_bps_),
663 encoder_max_bitrate_bps_,
664 static_cast<uint32_t>(max_padding_bitrate_),
665 !config_->suspend_below_min_bitrate, config_->track_id,
666 encoder_bitrate_priority_, has_packet_feedback_});
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200667 }
668}
669
670EncodedImageCallback::Result VideoSendStreamImpl::OnEncodedImage(
671 const EncodedImage& encoded_image,
672 const CodecSpecificInfo* codec_specific_info,
673 const RTPFragmentationHeader* fragmentation) {
674 // Encoded is called on whatever thread the real encoder implementation run
675 // on. In the case of hardware encoders, there might be several encoders
676 // running in parallel on different threads.
677 size_t simulcast_idx = 0;
678 if (codec_specific_info->codecType == kVideoCodecVP8) {
679 simulcast_idx = codec_specific_info->codecSpecific.VP8.simulcastIdx;
680 }
681 if (config_->post_encode_callback) {
682 config_->post_encode_callback->EncodedFrameCallback(EncodedFrame(
683 encoded_image._buffer, encoded_image._length, encoded_image._frameType,
684 simulcast_idx, encoded_image._timeStamp));
685 }
686 {
687 rtc::CritScope lock(&encoder_activity_crit_sect_);
688 if (check_encoder_activity_task_)
689 check_encoder_activity_task_->UpdateEncoderActivity();
690 }
691
692 fec_controller_->UpdateWithEncodedData(encoded_image._length,
693 encoded_image._frameType);
694 EncodedImageCallback::Result result = payload_router_.OnEncodedImage(
695 encoded_image, codec_specific_info, fragmentation);
696
697 RTC_DCHECK(codec_specific_info);
698
699 int layer = codec_specific_info->codecType == kVideoCodecVP8
700 ? codec_specific_info->codecSpecific.VP8.simulcastIdx
701 : 0;
702 {
703 rtc::CritScope lock(&ivf_writers_crit_);
704 if (file_writers_[layer].get()) {
705 bool ok = file_writers_[layer]->WriteFrame(
706 encoded_image, codec_specific_info->codecType);
707 RTC_DCHECK(ok);
708 }
709 }
710
711 return result;
712}
713
714void VideoSendStreamImpl::ConfigureProtection() {
715 RTC_DCHECK_RUN_ON(worker_queue_);
716
717 // Consistency of FlexFEC parameters is checked in MaybeCreateFlexfecSender.
718 const bool flexfec_enabled = (flexfec_sender_ != nullptr);
719
720 // Consistency of NACK and RED+ULPFEC parameters is checked in this function.
721 const bool nack_enabled = config_->rtp.nack.rtp_history_ms > 0;
722 int red_payload_type = config_->rtp.ulpfec.red_payload_type;
723 int ulpfec_payload_type = config_->rtp.ulpfec.ulpfec_payload_type;
724
725 // Shorthands.
726 auto IsRedEnabled = [&]() { return red_payload_type >= 0; };
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200727 auto IsUlpfecEnabled = [&]() { return ulpfec_payload_type >= 0; };
Kári Tristan Helgason798ee752018-07-11 16:04:57 +0200728 auto DisableRedAndUlpfec = [&]() {
729 red_payload_type = -1;
730 ulpfec_payload_type = -1;
731 };
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200732
733 if (webrtc::field_trial::IsEnabled("WebRTC-DisableUlpFecExperiment")) {
734 RTC_LOG(LS_INFO) << "Experiment to disable sending ULPFEC is enabled.";
Kári Tristan Helgason798ee752018-07-11 16:04:57 +0200735 DisableRedAndUlpfec();
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200736 }
737
738 // If enabled, FlexFEC takes priority over RED+ULPFEC.
739 if (flexfec_enabled) {
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200740 if (IsUlpfecEnabled()) {
741 RTC_LOG(LS_INFO)
742 << "Both FlexFEC and ULPFEC are configured. Disabling ULPFEC.";
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200743 }
Kári Tristan Helgason798ee752018-07-11 16:04:57 +0200744 DisableRedAndUlpfec();
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200745 }
746
747 // Payload types without picture ID cannot determine that a stream is complete
748 // without retransmitting FEC, so using ULPFEC + NACK for H.264 (for instance)
749 // is a waste of bandwidth since FEC packets still have to be transmitted.
750 // Note that this is not the case with FlexFEC.
751 if (nack_enabled && IsUlpfecEnabled() &&
752 !PayloadTypeSupportsSkippingFecPackets(config_->rtp.payload_name)) {
753 RTC_LOG(LS_WARNING)
754 << "Transmitting payload type without picture ID using "
755 "NACK+ULPFEC is a waste of bandwidth since ULPFEC packets "
756 "also have to be retransmitted. Disabling ULPFEC.";
Kári Tristan Helgason798ee752018-07-11 16:04:57 +0200757 DisableRedAndUlpfec();
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200758 }
759
760 // Verify payload types.
Kári Tristan Helgason798ee752018-07-11 16:04:57 +0200761 if (IsUlpfecEnabled() ^ IsRedEnabled()) {
762 RTC_LOG(LS_WARNING)
763 << "Only RED or only ULPFEC enabled, but not both. Disabling both.";
764 DisableRedAndUlpfec();
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200765 }
766
767 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
768 // Set NACK.
769 rtp_rtcp->SetStorePacketsStatus(true, kMinSendSidePacketHistorySize);
770 // Set RED/ULPFEC information.
771 rtp_rtcp->SetUlpfecConfig(red_payload_type, ulpfec_payload_type);
772 }
773
774 // Currently, both ULPFEC and FlexFEC use the same FEC rate calculation logic,
775 // so enable that logic if either of those FEC schemes are enabled.
776 fec_controller_->SetProtectionMethod(flexfec_enabled || IsUlpfecEnabled(),
777 nack_enabled);
778}
779
780void VideoSendStreamImpl::ConfigureSsrcs() {
781 RTC_DCHECK_RUN_ON(worker_queue_);
782 // Configure regular SSRCs.
783 for (size_t i = 0; i < config_->rtp.ssrcs.size(); ++i) {
784 uint32_t ssrc = config_->rtp.ssrcs[i];
785 RtpRtcp* const rtp_rtcp = rtp_rtcp_modules_[i];
786 rtp_rtcp->SetSSRC(ssrc);
787
788 // Restore RTP state if previous existed.
789 VideoSendStream::RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc);
790 if (it != suspended_ssrcs_.end())
791 rtp_rtcp->SetRtpState(it->second);
792 }
793
794 // Set up RTX if available.
795 if (config_->rtp.rtx.ssrcs.empty())
796 return;
797
798 // Configure RTX SSRCs.
799 RTC_DCHECK_EQ(config_->rtp.rtx.ssrcs.size(), config_->rtp.ssrcs.size());
800 for (size_t i = 0; i < config_->rtp.rtx.ssrcs.size(); ++i) {
801 uint32_t ssrc = config_->rtp.rtx.ssrcs[i];
802 RtpRtcp* const rtp_rtcp = rtp_rtcp_modules_[i];
803 rtp_rtcp->SetRtxSsrc(ssrc);
804 VideoSendStream::RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc);
805 if (it != suspended_ssrcs_.end())
806 rtp_rtcp->SetRtxState(it->second);
807 }
808
809 // Configure RTX payload types.
810 RTC_DCHECK_GE(config_->rtp.rtx.payload_type, 0);
811 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
812 rtp_rtcp->SetRtxSendPayloadType(config_->rtp.rtx.payload_type,
813 config_->rtp.payload_type);
814 rtp_rtcp->SetRtxSendStatus(kRtxRetransmitted | kRtxRedundantPayloads);
815 }
816 if (config_->rtp.ulpfec.red_payload_type != -1 &&
817 config_->rtp.ulpfec.red_rtx_payload_type != -1) {
818 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
819 rtp_rtcp->SetRtxSendPayloadType(config_->rtp.ulpfec.red_rtx_payload_type,
820 config_->rtp.ulpfec.red_payload_type);
821 }
822 }
823}
824
825std::map<uint32_t, RtpState> VideoSendStreamImpl::GetRtpStates() const {
826 RTC_DCHECK_RUN_ON(worker_queue_);
827 std::map<uint32_t, RtpState> rtp_states;
828
829 for (size_t i = 0; i < config_->rtp.ssrcs.size(); ++i) {
830 uint32_t ssrc = config_->rtp.ssrcs[i];
831 RTC_DCHECK_EQ(ssrc, rtp_rtcp_modules_[i]->SSRC());
832 rtp_states[ssrc] = rtp_rtcp_modules_[i]->GetRtpState();
833 }
834
835 for (size_t i = 0; i < config_->rtp.rtx.ssrcs.size(); ++i) {
836 uint32_t ssrc = config_->rtp.rtx.ssrcs[i];
837 rtp_states[ssrc] = rtp_rtcp_modules_[i]->GetRtxState();
838 }
839
840 if (flexfec_sender_) {
841 uint32_t ssrc = config_->rtp.flexfec.ssrc;
842 rtp_states[ssrc] = flexfec_sender_->GetRtpState();
843 }
844
845 return rtp_states;
846}
847
848std::map<uint32_t, RtpPayloadState> VideoSendStreamImpl::GetRtpPayloadStates()
849 const {
850 RTC_DCHECK_RUN_ON(worker_queue_);
851 return payload_router_.GetRtpPayloadStates();
852}
853
854void VideoSendStreamImpl::SignalNetworkState(NetworkState state) {
855 RTC_DCHECK_RUN_ON(worker_queue_);
856 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
857 rtp_rtcp->SetRTCPStatus(state == kNetworkUp ? config_->rtp.rtcp_mode
858 : RtcpMode::kOff);
859 }
860}
861
862uint32_t VideoSendStreamImpl::OnBitrateUpdated(uint32_t bitrate_bps,
863 uint8_t fraction_loss,
864 int64_t rtt,
865 int64_t probing_interval_ms) {
866 RTC_DCHECK_RUN_ON(worker_queue_);
867 RTC_DCHECK(payload_router_.IsActive())
868 << "VideoSendStream::Start has not been called.";
869
870 // Substract overhead from bitrate.
871 rtc::CritScope lock(&overhead_bytes_per_packet_crit_);
872 uint32_t payload_bitrate_bps = bitrate_bps;
873 if (send_side_bwe_with_overhead_) {
874 payload_bitrate_bps -= CalculateOverheadRateBps(
875 CalculatePacketRate(bitrate_bps,
876 config_->rtp.max_packet_size +
877 transport_overhead_bytes_per_packet_),
878 overhead_bytes_per_packet_ + transport_overhead_bytes_per_packet_,
879 bitrate_bps);
880 }
881
882 // Get the encoder target rate. It is the estimated network rate -
883 // protection overhead.
884 encoder_target_rate_bps_ = fec_controller_->UpdateFecRates(
885 payload_bitrate_bps, stats_proxy_->GetSendFrameRate(), fraction_loss,
886 loss_mask_vector_, rtt);
887 loss_mask_vector_.clear();
888
889 uint32_t encoder_overhead_rate_bps =
890 send_side_bwe_with_overhead_
891 ? CalculateOverheadRateBps(
892 CalculatePacketRate(encoder_target_rate_bps_,
893 config_->rtp.max_packet_size +
894 transport_overhead_bytes_per_packet_ -
895 overhead_bytes_per_packet_),
896 overhead_bytes_per_packet_ +
897 transport_overhead_bytes_per_packet_,
898 bitrate_bps - encoder_target_rate_bps_)
899 : 0;
900
901 // When the field trial "WebRTC-SendSideBwe-WithOverhead" is enabled
902 // protection_bitrate includes overhead.
903 uint32_t protection_bitrate =
904 bitrate_bps - (encoder_target_rate_bps_ + encoder_overhead_rate_bps);
905
906 encoder_target_rate_bps_ =
907 std::min(encoder_max_bitrate_bps_, encoder_target_rate_bps_);
908 video_stream_encoder_->OnBitrateUpdated(encoder_target_rate_bps_,
909 fraction_loss, rtt);
910 stats_proxy_->OnSetEncoderTargetRate(encoder_target_rate_bps_);
911 return protection_bitrate;
912}
913
914void VideoSendStreamImpl::EnableEncodedFrameRecording(
915 const std::vector<rtc::PlatformFile>& files,
916 size_t byte_limit) {
917 {
918 rtc::CritScope lock(&ivf_writers_crit_);
919 for (unsigned int i = 0; i < kMaxSimulcastStreams; ++i) {
920 if (i < files.size()) {
921 file_writers_[i] = IvfFileWriter::Wrap(rtc::File(files[i]), byte_limit);
922 } else {
923 file_writers_[i].reset();
924 }
925 }
926 }
927
928 if (!files.empty()) {
929 // Make a keyframe appear as early as possible in the logs, to give actually
930 // decodable output.
931 video_stream_encoder_->SendKeyFrame();
932 }
933}
934
935int VideoSendStreamImpl::ProtectionRequest(
936 const FecProtectionParams* delta_params,
937 const FecProtectionParams* key_params,
938 uint32_t* sent_video_rate_bps,
939 uint32_t* sent_nack_rate_bps,
940 uint32_t* sent_fec_rate_bps) {
941 RTC_DCHECK_RUN_ON(worker_queue_);
942 *sent_video_rate_bps = 0;
943 *sent_nack_rate_bps = 0;
944 *sent_fec_rate_bps = 0;
945 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
946 uint32_t not_used = 0;
947 uint32_t module_video_rate = 0;
948 uint32_t module_fec_rate = 0;
949 uint32_t module_nack_rate = 0;
950 rtp_rtcp->SetFecParameters(*delta_params, *key_params);
951 rtp_rtcp->BitrateSent(&not_used, &module_video_rate, &module_fec_rate,
952 &module_nack_rate);
953 *sent_video_rate_bps += module_video_rate;
954 *sent_nack_rate_bps += module_nack_rate;
955 *sent_fec_rate_bps += module_fec_rate;
956 }
957 return 0;
958}
959
960void VideoSendStreamImpl::OnOverheadChanged(size_t overhead_bytes_per_packet) {
961 rtc::CritScope lock(&overhead_bytes_per_packet_crit_);
962 overhead_bytes_per_packet_ = overhead_bytes_per_packet;
963}
964
965void VideoSendStreamImpl::SetTransportOverhead(
966 size_t transport_overhead_bytes_per_packet) {
967 if (transport_overhead_bytes_per_packet >= static_cast<int>(kPathMTU)) {
968 RTC_LOG(LS_ERROR) << "Transport overhead exceeds size of ethernet frame";
969 return;
970 }
971
972 transport_overhead_bytes_per_packet_ = transport_overhead_bytes_per_packet;
973
974 size_t rtp_packet_size =
975 std::min(config_->rtp.max_packet_size,
976 kPathMTU - transport_overhead_bytes_per_packet_);
977
978 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
979 rtp_rtcp->SetMaxRtpPacketSize(rtp_packet_size);
980 }
981}
982
983void VideoSendStreamImpl::OnPacketAdded(uint32_t ssrc, uint16_t seq_num) {
984 if (!worker_queue_->IsCurrent()) {
985 auto ptr = weak_ptr_;
986 worker_queue_->PostTask([=] {
987 if (!ptr.get())
988 return;
989 ptr->OnPacketAdded(ssrc, seq_num);
990 });
991 return;
992 }
993 const auto ssrcs = config_->rtp.ssrcs;
994 if (std::find(ssrcs.begin(), ssrcs.end(), ssrc) != ssrcs.end()) {
995 feedback_packet_seq_num_set_.insert(seq_num);
996 if (feedback_packet_seq_num_set_.size() > kSendSideSeqNumSetMaxSize) {
997 RTC_LOG(LS_WARNING) << "Feedback packet sequence number set exceed it's "
998 "max size', will get reset.";
999 feedback_packet_seq_num_set_.clear();
1000 }
1001 }
1002}
1003
1004void VideoSendStreamImpl::OnPacketFeedbackVector(
1005 const std::vector<PacketFeedback>& packet_feedback_vector) {
1006 if (!worker_queue_->IsCurrent()) {
1007 auto ptr = weak_ptr_;
1008 worker_queue_->PostTask([=] {
1009 if (!ptr.get())
1010 return;
1011 ptr->OnPacketFeedbackVector(packet_feedback_vector);
1012 });
1013 return;
1014 }
1015 // Lost feedbacks are not considered to be lost packets.
1016 for (const PacketFeedback& packet : packet_feedback_vector) {
1017 if (auto it = feedback_packet_seq_num_set_.find(packet.sequence_number) !=
1018 feedback_packet_seq_num_set_.end()) {
1019 const bool lost = packet.arrival_time_ms == PacketFeedback::kNotReceived;
1020 loss_mask_vector_.push_back(lost);
1021 feedback_packet_seq_num_set_.erase(it);
1022 }
1023 }
1024}
1025} // namespace internal
1026} // namespace webrtc