blob: aa9e6c98ec251b8b853d5783adfcd47cb7c3d1ec [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"
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +020018#include "modules/rtp_rtcp/source/rtp_sender.h"
19#include "rtc_base/checks.h"
20#include "rtc_base/experiments/alr_experiment.h"
21#include "rtc_base/file.h"
22#include "rtc_base/location.h"
23#include "rtc_base/logging.h"
24#include "rtc_base/numerics/safe_conversions.h"
25#include "rtc_base/trace_event.h"
26#include "system_wrappers/include/field_trial.h"
27
28namespace webrtc {
29namespace internal {
30namespace {
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +020031// Assume an average video stream has around 3 packets per frame (1 mbps / 30
32// fps / 1400B) A sequence number set with size 5500 will be able to store
33// packet sequence number for at least last 60 seconds.
34static const int kSendSideSeqNumSetMaxSize = 5500;
35
36// We don't do MTU discovery, so assume that we have the standard ethernet MTU.
37const size_t kPathMTU = 1500;
38
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +020039bool TransportSeqNumExtensionConfigured(const VideoSendStream::Config& config) {
40 const std::vector<RtpExtension>& extensions = config.rtp.extensions;
41 return std::find_if(
42 extensions.begin(), extensions.end(), [](const RtpExtension& ext) {
43 return ext.uri == RtpExtension::kTransportSequenceNumberUri;
44 }) != extensions.end();
45}
46
47const char kForcedFallbackFieldTrial[] =
48 "WebRTC-VP8-Forced-Fallback-Encoder-v2";
49
Danil Chapovalovb9b146c2018-06-15 12:28:07 +020050absl::optional<int> GetFallbackMinBpsFromFieldTrial() {
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +020051 if (!webrtc::field_trial::IsEnabled(kForcedFallbackFieldTrial))
Danil Chapovalovb9b146c2018-06-15 12:28:07 +020052 return absl::nullopt;
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +020053
54 std::string group =
55 webrtc::field_trial::FindFullName(kForcedFallbackFieldTrial);
56 if (group.empty())
Danil Chapovalovb9b146c2018-06-15 12:28:07 +020057 return absl::nullopt;
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +020058
59 int min_pixels;
60 int max_pixels;
61 int min_bps;
62 if (sscanf(group.c_str(), "Enabled-%d,%d,%d", &min_pixels, &max_pixels,
63 &min_bps) != 3) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +020064 return absl::nullopt;
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +020065 }
66
67 if (min_bps <= 0)
Danil Chapovalovb9b146c2018-06-15 12:28:07 +020068 return absl::nullopt;
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +020069
70 return min_bps;
71}
72
73int GetEncoderMinBitrateBps() {
74 const int kDefaultEncoderMinBitrateBps = 30000;
75 return GetFallbackMinBpsFromFieldTrial().value_or(
76 kDefaultEncoderMinBitrateBps);
77}
78
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +020079int CalculateMaxPadBitrateBps(std::vector<VideoStream> streams,
80 int min_transmit_bitrate_bps,
81 bool pad_to_min_bitrate) {
82 int pad_up_to_bitrate_bps = 0;
83 // Calculate max padding bitrate for a multi layer codec.
84 if (streams.size() > 1) {
85 // Pad to min bitrate of the highest layer.
86 pad_up_to_bitrate_bps = streams[streams.size() - 1].min_bitrate_bps;
87 // Add target_bitrate_bps of the lower layers.
88 for (size_t i = 0; i < streams.size() - 1; ++i)
89 pad_up_to_bitrate_bps += streams[i].target_bitrate_bps;
90 } else if (pad_to_min_bitrate) {
91 pad_up_to_bitrate_bps = streams[0].min_bitrate_bps;
92 }
93
94 pad_up_to_bitrate_bps =
95 std::max(pad_up_to_bitrate_bps, min_transmit_bitrate_bps);
96
97 return pad_up_to_bitrate_bps;
98}
99
100uint32_t CalculateOverheadRateBps(int packets_per_second,
101 size_t overhead_bytes_per_packet,
102 uint32_t max_overhead_bps) {
103 uint32_t overhead_bps =
104 static_cast<uint32_t>(8 * overhead_bytes_per_packet * packets_per_second);
105 return std::min(overhead_bps, max_overhead_bps);
106}
107
108int CalculatePacketRate(uint32_t bitrate_bps, size_t packet_size_bytes) {
109 size_t packet_size_bits = 8 * packet_size_bytes;
110 // Ceil for int value of bitrate_bps / packet_size_bits.
111 return static_cast<int>((bitrate_bps + packet_size_bits - 1) /
112 packet_size_bits);
113}
Stefan Holmer9416ef82018-07-19 10:34:38 +0200114
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200115RtpSenderObservers CreateObservers(CallStats* call_stats,
116 EncoderRtcpFeedback* encoder_feedback,
117 SendStatisticsProxy* stats_proxy,
118 SendDelayStats* send_delay_stats,
119 OverheadObserver* overhead_observer) {
120 RtpSenderObservers observers;
121 observers.rtcp_rtt_stats = call_stats;
122 observers.intra_frame_callback = encoder_feedback;
123 observers.rtcp_stats = stats_proxy;
124 observers.rtp_stats = stats_proxy;
125 observers.bitrate_observer = stats_proxy;
126 observers.frame_count_observer = stats_proxy;
127 observers.rtcp_type_observer = stats_proxy;
128 observers.send_delay_observer = stats_proxy;
129 observers.send_packet_observer = send_delay_stats;
130 observers.overhead_observer = overhead_observer;
131 return observers;
132}
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200133} // namespace
134
135// CheckEncoderActivityTask is used for tracking when the encoder last produced
136// and encoded video frame. If the encoder has not produced anything the last
137// kEncoderTimeOutMs we also want to stop sending padding.
138class VideoSendStreamImpl::CheckEncoderActivityTask : public rtc::QueuedTask {
139 public:
140 static const int kEncoderTimeOutMs = 2000;
141 explicit CheckEncoderActivityTask(
142 const rtc::WeakPtr<VideoSendStreamImpl>& send_stream)
143 : activity_(0), send_stream_(std::move(send_stream)), timed_out_(false) {}
144
145 void Stop() {
146 RTC_CHECK(task_checker_.CalledSequentially());
147 send_stream_.reset();
148 }
149
150 void UpdateEncoderActivity() {
151 // UpdateEncoderActivity is called from VideoSendStreamImpl::Encoded on
152 // whatever thread the real encoder implementation run on. In the case of
153 // hardware encoders, there might be several encoders
154 // running in parallel on different threads.
155 rtc::AtomicOps::ReleaseStore(&activity_, 1);
156 }
157
158 private:
159 bool Run() override {
160 RTC_CHECK(task_checker_.CalledSequentially());
161 if (!send_stream_)
162 return true;
163 if (!rtc::AtomicOps::AcquireLoad(&activity_)) {
164 if (!timed_out_) {
165 send_stream_->SignalEncoderTimedOut();
166 }
167 timed_out_ = true;
168 } else if (timed_out_) {
169 send_stream_->SignalEncoderActive();
170 timed_out_ = false;
171 }
172 rtc::AtomicOps::ReleaseStore(&activity_, 0);
173
174 rtc::TaskQueue::Current()->PostDelayedTask(
175 std::unique_ptr<rtc::QueuedTask>(this), kEncoderTimeOutMs);
176 // Return false to prevent this task from being deleted. Ownership has been
177 // transferred to the task queue when PostDelayedTask was called.
178 return false;
179 }
180 volatile int activity_;
181
182 rtc::SequencedTaskChecker task_checker_;
183 rtc::WeakPtr<VideoSendStreamImpl> send_stream_;
184 bool timed_out_;
185};
186
187VideoSendStreamImpl::VideoSendStreamImpl(
188 SendStatisticsProxy* stats_proxy,
189 rtc::TaskQueue* worker_queue,
190 CallStats* call_stats,
191 RtpTransportControllerSendInterface* transport,
Sebastian Jansson652dc912018-04-19 17:09:15 +0200192 BitrateAllocatorInterface* bitrate_allocator,
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200193 SendDelayStats* send_delay_stats,
Sebastian Jansson652dc912018-04-19 17:09:15 +0200194 VideoStreamEncoderInterface* video_stream_encoder,
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200195 RtcEventLog* event_log,
196 const VideoSendStream::Config* config,
197 int initial_encoder_max_bitrate,
198 double initial_encoder_bitrate_priority,
199 std::map<uint32_t, RtpState> suspended_ssrcs,
200 std::map<uint32_t, RtpPayloadState> suspended_payload_states,
201 VideoEncoderConfig::ContentType content_type,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200202 std::unique_ptr<FecController> fec_controller)
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200203 : send_side_bwe_with_overhead_(
204 webrtc::field_trial::IsEnabled("WebRTC-SendSideBwe-WithOverhead")),
205 stats_proxy_(stats_proxy),
206 config_(config),
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200207 fec_controller_(std::move(fec_controller)),
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200208 worker_queue_(worker_queue),
209 check_encoder_activity_task_(nullptr),
210 call_stats_(call_stats),
211 transport_(transport),
212 bitrate_allocator_(bitrate_allocator),
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200213 max_padding_bitrate_(0),
214 encoder_min_bitrate_bps_(0),
215 encoder_target_rate_bps_(0),
216 encoder_bitrate_priority_(initial_encoder_bitrate_priority),
217 has_packet_feedback_(false),
218 video_stream_encoder_(video_stream_encoder),
219 encoder_feedback_(Clock::GetRealTimeClock(),
220 config_->rtp.ssrcs,
221 video_stream_encoder),
222 bandwidth_observer_(transport->GetBandwidthObserver()),
Stefan Holmer9416ef82018-07-19 10:34:38 +0200223 rtp_video_sender_(
224 transport_->CreateRtpVideoSender(config_->rtp.ssrcs,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200225 suspended_ssrcs,
226 suspended_payload_states,
227 config_->rtp,
228 config_->rtcp,
229 config_->send_transport,
230 CreateObservers(call_stats,
231 &encoder_feedback_,
232 stats_proxy_,
233 send_delay_stats,
234 this),
235 event_log)),
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200236 weak_ptr_factory_(this),
237 overhead_bytes_per_packet_(0),
238 transport_overhead_bytes_per_packet_(0) {
239 RTC_DCHECK_RUN_ON(worker_queue_);
240 RTC_LOG(LS_INFO) << "VideoSendStreamInternal: " << config_->ToString();
241 weak_ptr_ = weak_ptr_factory_.GetWeakPtr();
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200242
243 RTC_DCHECK(!config_->rtp.ssrcs.empty());
244 RTC_DCHECK(call_stats_);
245 RTC_DCHECK(transport_);
246 RTC_DCHECK_NE(initial_encoder_max_bitrate, 0);
247
248 if (initial_encoder_max_bitrate > 0) {
249 encoder_max_bitrate_bps_ =
250 rtc::dchecked_cast<uint32_t>(initial_encoder_max_bitrate);
251 } else {
252 // TODO(srte): Make sure max bitrate is not set to negative values. We don't
253 // have any way to handle unset values in downstream code, such as the
254 // bitrate allocator. Previously -1 was implicitly casted to UINT32_MAX, a
255 // behaviour that is not safe. Converting to 10 Mbps should be safe for
256 // reasonable use cases as it allows adding the max of multiple streams
257 // without wrappping around.
258 const int kFallbackMaxBitrateBps = 10000000;
259 RTC_DLOG(LS_ERROR) << "ERROR: Initial encoder max bitrate = "
260 << initial_encoder_max_bitrate << " which is <= 0!";
261 RTC_DLOG(LS_INFO) << "Using default encoder max bitrate = 10 Mbps";
262 encoder_max_bitrate_bps_ = kFallbackMaxBitrateBps;
263 }
264
265 RTC_CHECK(AlrExperimentSettings::MaxOneFieldTrialEnabled());
266 // If send-side BWE is enabled, check if we should apply updated probing and
267 // pacing settings.
268 if (TransportSeqNumExtensionConfigured(*config_)) {
269 has_packet_feedback_ = true;
270
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200271 absl::optional<AlrExperimentSettings> alr_settings;
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200272 if (content_type == VideoEncoderConfig::ContentType::kScreen) {
273 alr_settings = AlrExperimentSettings::CreateFromFieldTrial(
274 AlrExperimentSettings::kScreenshareProbingBweExperimentName);
275 } else {
276 alr_settings = AlrExperimentSettings::CreateFromFieldTrial(
277 AlrExperimentSettings::kStrictPacingAndProbingExperimentName);
278 }
279 if (alr_settings) {
280 transport->EnablePeriodicAlrProbing(true);
281 transport->SetPacingFactor(alr_settings->pacing_factor);
282 configured_pacing_factor_ = alr_settings->pacing_factor;
283 transport->SetQueueTimeLimit(alr_settings->max_paced_queue_time);
284 } else {
285 transport->EnablePeriodicAlrProbing(false);
286 transport->SetPacingFactor(PacedSender::kDefaultPaceMultiplier);
287 configured_pacing_factor_ = PacedSender::kDefaultPaceMultiplier;
288 transport->SetQueueTimeLimit(PacedSender::kMaxQueueLengthMs);
289 }
290 }
291
292 if (config_->periodic_alr_bandwidth_probing) {
293 transport->EnablePeriodicAlrProbing(true);
294 }
295
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200296 // Currently, both ULPFEC and FlexFEC use the same FEC rate calculation logic,
297 // so enable that logic if either of those FEC schemes are enabled.
Stefan Holmer9416ef82018-07-19 10:34:38 +0200298 fec_controller_->SetProtectionMethod(rtp_video_sender_->FecEnabled(),
299 rtp_video_sender_->NackEnabled());
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200300
301 fec_controller_->SetProtectionCallback(this);
302 // Signal congestion controller this object is ready for OnPacket* callbacks.
303 if (fec_controller_->UseLossVectorMask()) {
304 transport_->RegisterPacketFeedbackObserver(this);
305 }
306
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200307 RTC_DCHECK_GE(config_->rtp.payload_type, 0);
308 RTC_DCHECK_LE(config_->rtp.payload_type, 127);
309
310 video_stream_encoder_->SetStartBitrate(
311 bitrate_allocator_->GetStartBitrate(this));
312
313 // Only request rotation at the source when we positively know that the remote
314 // side doesn't support the rotation extension. This allows us to prepare the
315 // encoder in the expectation that rotation is supported - which is the common
316 // case.
317 bool rotation_applied =
318 std::find_if(config_->rtp.extensions.begin(),
319 config_->rtp.extensions.end(),
320 [](const RtpExtension& extension) {
321 return extension.uri == RtpExtension::kVideoRotationUri;
322 }) == config_->rtp.extensions.end();
323
324 video_stream_encoder_->SetSink(this, rotation_applied);
325}
326
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200327VideoSendStreamImpl::~VideoSendStreamImpl() {
328 RTC_DCHECK_RUN_ON(worker_queue_);
Stefan Holmer9416ef82018-07-19 10:34:38 +0200329 RTC_DCHECK(!rtp_video_sender_->IsActive())
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200330 << "VideoSendStreamImpl::Stop not called";
331 RTC_LOG(LS_INFO) << "~VideoSendStreamInternal: " << config_->ToString();
332 if (fec_controller_->UseLossVectorMask()) {
333 transport_->DeRegisterPacketFeedbackObserver(this);
334 }
Stefan Holmer9416ef82018-07-19 10:34:38 +0200335 transport_->DestroyRtpVideoSender(rtp_video_sender_);
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200336}
337
338void VideoSendStreamImpl::RegisterProcessThread(
339 ProcessThread* module_process_thread) {
Stefan Holmer9416ef82018-07-19 10:34:38 +0200340 rtp_video_sender_->RegisterProcessThread(module_process_thread);
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200341}
342
343void VideoSendStreamImpl::DeRegisterProcessThread() {
Stefan Holmer9416ef82018-07-19 10:34:38 +0200344 rtp_video_sender_->DeRegisterProcessThread();
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200345}
346
347bool VideoSendStreamImpl::DeliverRtcp(const uint8_t* packet, size_t length) {
348 // Runs on a network thread.
349 RTC_DCHECK(!worker_queue_->IsCurrent());
Stefan Holmer9416ef82018-07-19 10:34:38 +0200350 rtp_video_sender_->DeliverRtcp(packet, length);
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200351 return true;
352}
353
354void VideoSendStreamImpl::UpdateActiveSimulcastLayers(
355 const std::vector<bool> active_layers) {
356 RTC_DCHECK_RUN_ON(worker_queue_);
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200357 RTC_LOG(LS_INFO) << "VideoSendStream::UpdateActiveSimulcastLayers";
Stefan Holmer9416ef82018-07-19 10:34:38 +0200358 bool previously_active = rtp_video_sender_->IsActive();
359 rtp_video_sender_->SetActiveModules(active_layers);
360 if (!rtp_video_sender_->IsActive() && previously_active) {
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200361 // Payload router switched from active to inactive.
362 StopVideoSendStream();
Stefan Holmer9416ef82018-07-19 10:34:38 +0200363 } else if (rtp_video_sender_->IsActive() && !previously_active) {
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200364 // Payload router switched from inactive to active.
365 StartupVideoSendStream();
366 }
367}
368
369void VideoSendStreamImpl::Start() {
370 RTC_DCHECK_RUN_ON(worker_queue_);
371 RTC_LOG(LS_INFO) << "VideoSendStream::Start";
Stefan Holmer9416ef82018-07-19 10:34:38 +0200372 if (rtp_video_sender_->IsActive())
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200373 return;
374 TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Start");
Stefan Holmer9416ef82018-07-19 10:34:38 +0200375 rtp_video_sender_->SetActive(true);
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200376 StartupVideoSendStream();
377}
378
379void VideoSendStreamImpl::StartupVideoSendStream() {
380 RTC_DCHECK_RUN_ON(worker_queue_);
381 bitrate_allocator_->AddObserver(
Sebastian Jansson24ad7202018-04-19 08:25:12 +0200382 this,
383 MediaStreamAllocationConfig{
384 static_cast<uint32_t>(encoder_min_bitrate_bps_),
385 encoder_max_bitrate_bps_, static_cast<uint32_t>(max_padding_bitrate_),
386 !config_->suspend_below_min_bitrate, config_->track_id,
387 encoder_bitrate_priority_, has_packet_feedback_});
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200388 // Start monitoring encoder activity.
389 {
390 rtc::CritScope lock(&encoder_activity_crit_sect_);
391 RTC_DCHECK(!check_encoder_activity_task_);
392 check_encoder_activity_task_ = new CheckEncoderActivityTask(weak_ptr_);
393 worker_queue_->PostDelayedTask(
394 std::unique_ptr<rtc::QueuedTask>(check_encoder_activity_task_),
395 CheckEncoderActivityTask::kEncoderTimeOutMs);
396 }
397
398 video_stream_encoder_->SendKeyFrame();
399}
400
401void VideoSendStreamImpl::Stop() {
402 RTC_DCHECK_RUN_ON(worker_queue_);
403 RTC_LOG(LS_INFO) << "VideoSendStream::Stop";
Stefan Holmer9416ef82018-07-19 10:34:38 +0200404 if (!rtp_video_sender_->IsActive())
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200405 return;
406 TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Stop");
Stefan Holmer9416ef82018-07-19 10:34:38 +0200407 rtp_video_sender_->SetActive(false);
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200408 StopVideoSendStream();
409}
410
411void VideoSendStreamImpl::StopVideoSendStream() {
412 bitrate_allocator_->RemoveObserver(this);
413 {
414 rtc::CritScope lock(&encoder_activity_crit_sect_);
415 check_encoder_activity_task_->Stop();
416 check_encoder_activity_task_ = nullptr;
417 }
418 video_stream_encoder_->OnBitrateUpdated(0, 0, 0);
419 stats_proxy_->OnSetEncoderTargetRate(0);
420}
421
422void VideoSendStreamImpl::SignalEncoderTimedOut() {
423 RTC_DCHECK_RUN_ON(worker_queue_);
424 // If the encoder has not produced anything the last kEncoderTimeOutMs and it
425 // is supposed to, deregister as BitrateAllocatorObserver. This can happen
426 // if a camera stops producing frames.
427 if (encoder_target_rate_bps_ > 0) {
428 RTC_LOG(LS_INFO) << "SignalEncoderTimedOut, Encoder timed out.";
429 bitrate_allocator_->RemoveObserver(this);
430 }
431}
432
433void VideoSendStreamImpl::OnBitrateAllocationUpdated(
Erik Språng566124a2018-04-23 12:32:22 +0200434 const VideoBitrateAllocation& allocation) {
Stefan Holmer9416ef82018-07-19 10:34:38 +0200435 rtp_video_sender_->OnBitrateAllocationUpdated(allocation);
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200436}
437
438void VideoSendStreamImpl::SignalEncoderActive() {
439 RTC_DCHECK_RUN_ON(worker_queue_);
440 RTC_LOG(LS_INFO) << "SignalEncoderActive, Encoder is active.";
441 bitrate_allocator_->AddObserver(
Sebastian Jansson24ad7202018-04-19 08:25:12 +0200442 this,
443 MediaStreamAllocationConfig{
444 static_cast<uint32_t>(encoder_min_bitrate_bps_),
445 encoder_max_bitrate_bps_, static_cast<uint32_t>(max_padding_bitrate_),
446 !config_->suspend_below_min_bitrate, config_->track_id,
447 encoder_bitrate_priority_, has_packet_feedback_});
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200448}
449
450void VideoSendStreamImpl::OnEncoderConfigurationChanged(
451 std::vector<VideoStream> streams,
452 int min_transmit_bitrate_bps) {
453 if (!worker_queue_->IsCurrent()) {
454 rtc::WeakPtr<VideoSendStreamImpl> send_stream = weak_ptr_;
455 worker_queue_->PostTask([send_stream, streams, min_transmit_bitrate_bps]() {
456 if (send_stream)
457 send_stream->OnEncoderConfigurationChanged(std::move(streams),
458 min_transmit_bitrate_bps);
459 });
460 return;
461 }
462 RTC_DCHECK_GE(config_->rtp.ssrcs.size(), streams.size());
463 TRACE_EVENT0("webrtc", "VideoSendStream::OnEncoderConfigurationChanged");
464 RTC_DCHECK_GE(config_->rtp.ssrcs.size(), streams.size());
465 RTC_DCHECK_RUN_ON(worker_queue_);
466
467 encoder_min_bitrate_bps_ =
468 std::max(streams[0].min_bitrate_bps, GetEncoderMinBitrateBps());
469 encoder_max_bitrate_bps_ = 0;
470 double stream_bitrate_priority_sum = 0;
471 for (const auto& stream : streams) {
472 // We don't want to allocate more bitrate than needed to inactive streams.
473 encoder_max_bitrate_bps_ += stream.active ? stream.max_bitrate_bps : 0;
474 if (stream.bitrate_priority) {
475 RTC_DCHECK_GT(*stream.bitrate_priority, 0);
476 stream_bitrate_priority_sum += *stream.bitrate_priority;
477 }
478 }
479 RTC_DCHECK_GT(stream_bitrate_priority_sum, 0);
480 encoder_bitrate_priority_ = stream_bitrate_priority_sum;
481 encoder_max_bitrate_bps_ =
482 std::max(static_cast<uint32_t>(encoder_min_bitrate_bps_),
483 encoder_max_bitrate_bps_);
“Michael277a6562018-06-01 14:09:19 -0500484
485 const VideoCodecType codec_type =
486 PayloadStringToCodecType(config_->rtp.payload_name);
487 if (codec_type == kVideoCodecVP9) {
488 max_padding_bitrate_ = streams[0].target_bitrate_bps;
489 } else {
490 max_padding_bitrate_ = CalculateMaxPadBitrateBps(
491 streams, min_transmit_bitrate_bps, config_->suspend_below_min_bitrate);
492 }
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200493
494 // Clear stats for disabled layers.
495 for (size_t i = streams.size(); i < config_->rtp.ssrcs.size(); ++i) {
496 stats_proxy_->OnInactiveSsrc(config_->rtp.ssrcs[i]);
497 }
498
499 const size_t num_temporal_layers =
500 streams.back().num_temporal_layers.value_or(1);
501 fec_controller_->SetEncodingData(streams[0].width, streams[0].height,
502 num_temporal_layers,
503 config_->rtp.max_packet_size);
504
Stefan Holmer9416ef82018-07-19 10:34:38 +0200505 if (rtp_video_sender_->IsActive()) {
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200506 // The send stream is started already. Update the allocator with new bitrate
507 // limits.
508 bitrate_allocator_->AddObserver(
Sebastian Jansson24ad7202018-04-19 08:25:12 +0200509 this, MediaStreamAllocationConfig{
510 static_cast<uint32_t>(encoder_min_bitrate_bps_),
511 encoder_max_bitrate_bps_,
512 static_cast<uint32_t>(max_padding_bitrate_),
513 !config_->suspend_below_min_bitrate, config_->track_id,
514 encoder_bitrate_priority_, has_packet_feedback_});
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200515 }
516}
517
518EncodedImageCallback::Result VideoSendStreamImpl::OnEncodedImage(
519 const EncodedImage& encoded_image,
520 const CodecSpecificInfo* codec_specific_info,
521 const RTPFragmentationHeader* fragmentation) {
522 // Encoded is called on whatever thread the real encoder implementation run
523 // on. In the case of hardware encoders, there might be several encoders
524 // running in parallel on different threads.
Niels Möllerd3b8c632018-08-27 15:33:42 +0200525 const size_t simulcast_idx =
526 (codec_specific_info->codecType != kVideoCodecVP9)
527 ? encoded_image.SpatialIndex().value_or(0)
528 : 0;
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200529 if (config_->post_encode_callback) {
Niels Möllerd3b8c632018-08-27 15:33:42 +0200530 // TODO(nisse): Delete webrtc::EncodedFrame class, pass EncodedImage
531 // instead.
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200532 config_->post_encode_callback->EncodedFrameCallback(EncodedFrame(
533 encoded_image._buffer, encoded_image._length, encoded_image._frameType,
Niels Möller23775882018-08-16 10:24:12 +0200534 simulcast_idx, encoded_image.Timestamp()));
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200535 }
536 {
537 rtc::CritScope lock(&encoder_activity_crit_sect_);
538 if (check_encoder_activity_task_)
539 check_encoder_activity_task_->UpdateEncoderActivity();
540 }
541
542 fec_controller_->UpdateWithEncodedData(encoded_image._length,
543 encoded_image._frameType);
Niels Möller1beef1a2018-09-03 14:21:44 +0200544 return rtp_video_sender_->OnEncodedImage(encoded_image, codec_specific_info,
545 fragmentation);
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200546}
547
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200548std::map<uint32_t, RtpState> VideoSendStreamImpl::GetRtpStates() const {
Stefan Holmer9416ef82018-07-19 10:34:38 +0200549 return rtp_video_sender_->GetRtpStates();
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200550}
551
552std::map<uint32_t, RtpPayloadState> VideoSendStreamImpl::GetRtpPayloadStates()
553 const {
Stefan Holmer9416ef82018-07-19 10:34:38 +0200554 return rtp_video_sender_->GetRtpPayloadStates();
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200555}
556
557uint32_t VideoSendStreamImpl::OnBitrateUpdated(uint32_t bitrate_bps,
558 uint8_t fraction_loss,
559 int64_t rtt,
560 int64_t probing_interval_ms) {
561 RTC_DCHECK_RUN_ON(worker_queue_);
Stefan Holmer9416ef82018-07-19 10:34:38 +0200562 RTC_DCHECK(rtp_video_sender_->IsActive())
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200563 << "VideoSendStream::Start has not been called.";
564
565 // Substract overhead from bitrate.
566 rtc::CritScope lock(&overhead_bytes_per_packet_crit_);
567 uint32_t payload_bitrate_bps = bitrate_bps;
568 if (send_side_bwe_with_overhead_) {
569 payload_bitrate_bps -= CalculateOverheadRateBps(
570 CalculatePacketRate(bitrate_bps,
571 config_->rtp.max_packet_size +
572 transport_overhead_bytes_per_packet_),
573 overhead_bytes_per_packet_ + transport_overhead_bytes_per_packet_,
574 bitrate_bps);
575 }
576
577 // Get the encoder target rate. It is the estimated network rate -
578 // protection overhead.
579 encoder_target_rate_bps_ = fec_controller_->UpdateFecRates(
580 payload_bitrate_bps, stats_proxy_->GetSendFrameRate(), fraction_loss,
581 loss_mask_vector_, rtt);
582 loss_mask_vector_.clear();
583
584 uint32_t encoder_overhead_rate_bps =
585 send_side_bwe_with_overhead_
586 ? CalculateOverheadRateBps(
587 CalculatePacketRate(encoder_target_rate_bps_,
588 config_->rtp.max_packet_size +
589 transport_overhead_bytes_per_packet_ -
590 overhead_bytes_per_packet_),
591 overhead_bytes_per_packet_ +
592 transport_overhead_bytes_per_packet_,
593 bitrate_bps - encoder_target_rate_bps_)
594 : 0;
595
596 // When the field trial "WebRTC-SendSideBwe-WithOverhead" is enabled
597 // protection_bitrate includes overhead.
598 uint32_t protection_bitrate =
599 bitrate_bps - (encoder_target_rate_bps_ + encoder_overhead_rate_bps);
600
601 encoder_target_rate_bps_ =
602 std::min(encoder_max_bitrate_bps_, encoder_target_rate_bps_);
603 video_stream_encoder_->OnBitrateUpdated(encoder_target_rate_bps_,
604 fraction_loss, rtt);
605 stats_proxy_->OnSetEncoderTargetRate(encoder_target_rate_bps_);
606 return protection_bitrate;
607}
608
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200609int VideoSendStreamImpl::ProtectionRequest(
610 const FecProtectionParams* delta_params,
611 const FecProtectionParams* key_params,
612 uint32_t* sent_video_rate_bps,
613 uint32_t* sent_nack_rate_bps,
614 uint32_t* sent_fec_rate_bps) {
615 RTC_DCHECK_RUN_ON(worker_queue_);
Stefan Holmer9416ef82018-07-19 10:34:38 +0200616 rtp_video_sender_->ProtectionRequest(delta_params, key_params,
617 sent_video_rate_bps, sent_nack_rate_bps,
618 sent_fec_rate_bps);
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200619 return 0;
620}
621
622void VideoSendStreamImpl::OnOverheadChanged(size_t overhead_bytes_per_packet) {
623 rtc::CritScope lock(&overhead_bytes_per_packet_crit_);
624 overhead_bytes_per_packet_ = overhead_bytes_per_packet;
625}
626
627void VideoSendStreamImpl::SetTransportOverhead(
628 size_t transport_overhead_bytes_per_packet) {
629 if (transport_overhead_bytes_per_packet >= static_cast<int>(kPathMTU)) {
630 RTC_LOG(LS_ERROR) << "Transport overhead exceeds size of ethernet frame";
631 return;
632 }
633
634 transport_overhead_bytes_per_packet_ = transport_overhead_bytes_per_packet;
635
636 size_t rtp_packet_size =
637 std::min(config_->rtp.max_packet_size,
638 kPathMTU - transport_overhead_bytes_per_packet_);
639
Stefan Holmer9416ef82018-07-19 10:34:38 +0200640 rtp_video_sender_->SetMaxRtpPacketSize(rtp_packet_size);
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200641}
642
643void VideoSendStreamImpl::OnPacketAdded(uint32_t ssrc, uint16_t seq_num) {
644 if (!worker_queue_->IsCurrent()) {
645 auto ptr = weak_ptr_;
646 worker_queue_->PostTask([=] {
647 if (!ptr.get())
648 return;
649 ptr->OnPacketAdded(ssrc, seq_num);
650 });
651 return;
652 }
653 const auto ssrcs = config_->rtp.ssrcs;
654 if (std::find(ssrcs.begin(), ssrcs.end(), ssrc) != ssrcs.end()) {
655 feedback_packet_seq_num_set_.insert(seq_num);
656 if (feedback_packet_seq_num_set_.size() > kSendSideSeqNumSetMaxSize) {
657 RTC_LOG(LS_WARNING) << "Feedback packet sequence number set exceed it's "
658 "max size', will get reset.";
659 feedback_packet_seq_num_set_.clear();
660 }
661 }
662}
663
664void VideoSendStreamImpl::OnPacketFeedbackVector(
665 const std::vector<PacketFeedback>& packet_feedback_vector) {
666 if (!worker_queue_->IsCurrent()) {
667 auto ptr = weak_ptr_;
668 worker_queue_->PostTask([=] {
669 if (!ptr.get())
670 return;
671 ptr->OnPacketFeedbackVector(packet_feedback_vector);
672 });
673 return;
674 }
675 // Lost feedbacks are not considered to be lost packets.
676 for (const PacketFeedback& packet : packet_feedback_vector) {
Benoît Lizé86fbea12018-06-20 14:00:34 +0200677 auto it = feedback_packet_seq_num_set_.find(packet.sequence_number);
678 if (it != feedback_packet_seq_num_set_.end()) {
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200679 const bool lost = packet.arrival_time_ms == PacketFeedback::kNotReceived;
680 loss_mask_vector_.push_back(lost);
681 feedback_packet_seq_num_set_.erase(it);
682 }
683 }
684}
685} // namespace internal
686} // namespace webrtc