blob: b725e63d68a3ab54a8d81529e75091b362a596b4 [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
Erik Språng4e193e42018-09-14 19:01:58 +020032// Max positive size difference to treat allocations as "similar".
33static constexpr int kMaxVbaSizeDifferencePercent = 10;
34// Max time we will throttle similar video bitrate allocations.
35static constexpr int64_t kMaxVbaThrottleTimeMs = 500;
36
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +020037bool TransportSeqNumExtensionConfigured(const VideoSendStream::Config& config) {
38 const std::vector<RtpExtension>& extensions = config.rtp.extensions;
39 return std::find_if(
40 extensions.begin(), extensions.end(), [](const RtpExtension& ext) {
41 return ext.uri == RtpExtension::kTransportSequenceNumberUri;
42 }) != extensions.end();
43}
44
45const char kForcedFallbackFieldTrial[] =
46 "WebRTC-VP8-Forced-Fallback-Encoder-v2";
47
Danil Chapovalovb9b146c2018-06-15 12:28:07 +020048absl::optional<int> GetFallbackMinBpsFromFieldTrial() {
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +020049 if (!webrtc::field_trial::IsEnabled(kForcedFallbackFieldTrial))
Danil Chapovalovb9b146c2018-06-15 12:28:07 +020050 return absl::nullopt;
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +020051
52 std::string group =
53 webrtc::field_trial::FindFullName(kForcedFallbackFieldTrial);
54 if (group.empty())
Danil Chapovalovb9b146c2018-06-15 12:28:07 +020055 return absl::nullopt;
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +020056
57 int min_pixels;
58 int max_pixels;
59 int min_bps;
60 if (sscanf(group.c_str(), "Enabled-%d,%d,%d", &min_pixels, &max_pixels,
61 &min_bps) != 3) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +020062 return absl::nullopt;
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +020063 }
64
65 if (min_bps <= 0)
Danil Chapovalovb9b146c2018-06-15 12:28:07 +020066 return absl::nullopt;
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +020067
68 return min_bps;
69}
70
71int GetEncoderMinBitrateBps() {
72 const int kDefaultEncoderMinBitrateBps = 30000;
73 return GetFallbackMinBpsFromFieldTrial().value_or(
74 kDefaultEncoderMinBitrateBps);
75}
76
Erik Språngb57ab382018-09-13 10:52:38 +020077// Calculate max padding bitrate for a multi layer codec.
78int CalculateMaxPadBitrateBps(const std::vector<VideoStream>& streams,
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +020079 int min_transmit_bitrate_bps,
Erik Språngb57ab382018-09-13 10:52:38 +020080 bool pad_to_min_bitrate,
81 bool alr_probing) {
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +020082 int pad_up_to_bitrate_bps = 0;
Erik Språngb57ab382018-09-13 10:52:38 +020083
84 // Filter out only the active streams;
85 std::vector<VideoStream> active_streams;
86 for (const VideoStream& stream : streams) {
87 if (stream.active)
88 active_streams.emplace_back(stream);
89 }
90
91 if (active_streams.size() > 1) {
92 if (alr_probing) {
93 // With alr probing, just pad to the min bitrate of the lowest stream,
94 // probing will handle the rest of the rampup.
95 pad_up_to_bitrate_bps = active_streams[0].min_bitrate_bps;
96 } else {
97 // Pad to min bitrate of the highest layer.
98 pad_up_to_bitrate_bps =
99 active_streams[active_streams.size() - 1].min_bitrate_bps;
100 // Add target_bitrate_bps of the lower layers.
101 for (size_t i = 0; i < active_streams.size() - 1; ++i)
102 pad_up_to_bitrate_bps += active_streams[i].target_bitrate_bps;
103 }
104 } else if (!active_streams.empty() && pad_to_min_bitrate) {
105 pad_up_to_bitrate_bps = active_streams[0].min_bitrate_bps;
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200106 }
107
108 pad_up_to_bitrate_bps =
109 std::max(pad_up_to_bitrate_bps, min_transmit_bitrate_bps);
110
111 return pad_up_to_bitrate_bps;
112}
113
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200114RtpSenderObservers CreateObservers(CallStats* call_stats,
115 EncoderRtcpFeedback* encoder_feedback,
116 SendStatisticsProxy* stats_proxy,
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200117 SendDelayStats* send_delay_stats) {
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200118 RtpSenderObservers observers;
119 observers.rtcp_rtt_stats = call_stats;
120 observers.intra_frame_callback = encoder_feedback;
121 observers.rtcp_stats = stats_proxy;
122 observers.rtp_stats = stats_proxy;
123 observers.bitrate_observer = stats_proxy;
124 observers.frame_count_observer = stats_proxy;
125 observers.rtcp_type_observer = stats_proxy;
126 observers.send_delay_observer = stats_proxy;
127 observers.send_packet_observer = send_delay_stats;
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200128 return observers;
129}
Erik Språngb57ab382018-09-13 10:52:38 +0200130
131absl::optional<AlrExperimentSettings> GetAlrSettings(
132 VideoEncoderConfig::ContentType content_type) {
133 if (content_type == VideoEncoderConfig::ContentType::kScreen) {
134 return AlrExperimentSettings::CreateFromFieldTrial(
135 AlrExperimentSettings::kScreenshareProbingBweExperimentName);
136 }
137 return AlrExperimentSettings::CreateFromFieldTrial(
138 AlrExperimentSettings::kStrictPacingAndProbingExperimentName);
139}
Erik Språng4e193e42018-09-14 19:01:58 +0200140
141bool SameStreamsEnabled(const VideoBitrateAllocation& lhs,
142 const VideoBitrateAllocation& rhs) {
143 for (size_t si = 0; si < kMaxSpatialLayers; ++si) {
144 for (size_t ti = 0; ti < kMaxTemporalStreams; ++ti) {
145 if (lhs.HasBitrate(si, ti) != rhs.HasBitrate(si, ti)) {
146 return false;
147 }
148 }
149 }
150 return true;
151}
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200152} // namespace
153
154// CheckEncoderActivityTask is used for tracking when the encoder last produced
155// and encoded video frame. If the encoder has not produced anything the last
156// kEncoderTimeOutMs we also want to stop sending padding.
157class VideoSendStreamImpl::CheckEncoderActivityTask : public rtc::QueuedTask {
158 public:
159 static const int kEncoderTimeOutMs = 2000;
160 explicit CheckEncoderActivityTask(
161 const rtc::WeakPtr<VideoSendStreamImpl>& send_stream)
162 : activity_(0), send_stream_(std::move(send_stream)), timed_out_(false) {}
163
164 void Stop() {
165 RTC_CHECK(task_checker_.CalledSequentially());
166 send_stream_.reset();
167 }
168
169 void UpdateEncoderActivity() {
170 // UpdateEncoderActivity is called from VideoSendStreamImpl::Encoded on
171 // whatever thread the real encoder implementation run on. In the case of
172 // hardware encoders, there might be several encoders
173 // running in parallel on different threads.
174 rtc::AtomicOps::ReleaseStore(&activity_, 1);
175 }
176
177 private:
178 bool Run() override {
179 RTC_CHECK(task_checker_.CalledSequentially());
180 if (!send_stream_)
181 return true;
182 if (!rtc::AtomicOps::AcquireLoad(&activity_)) {
183 if (!timed_out_) {
184 send_stream_->SignalEncoderTimedOut();
185 }
186 timed_out_ = true;
187 } else if (timed_out_) {
188 send_stream_->SignalEncoderActive();
189 timed_out_ = false;
190 }
191 rtc::AtomicOps::ReleaseStore(&activity_, 0);
192
193 rtc::TaskQueue::Current()->PostDelayedTask(
194 std::unique_ptr<rtc::QueuedTask>(this), kEncoderTimeOutMs);
195 // Return false to prevent this task from being deleted. Ownership has been
196 // transferred to the task queue when PostDelayedTask was called.
197 return false;
198 }
199 volatile int activity_;
200
201 rtc::SequencedTaskChecker task_checker_;
202 rtc::WeakPtr<VideoSendStreamImpl> send_stream_;
203 bool timed_out_;
204};
205
206VideoSendStreamImpl::VideoSendStreamImpl(
207 SendStatisticsProxy* stats_proxy,
208 rtc::TaskQueue* worker_queue,
209 CallStats* call_stats,
210 RtpTransportControllerSendInterface* transport,
Sebastian Jansson652dc912018-04-19 17:09:15 +0200211 BitrateAllocatorInterface* bitrate_allocator,
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200212 SendDelayStats* send_delay_stats,
Sebastian Jansson652dc912018-04-19 17:09:15 +0200213 VideoStreamEncoderInterface* video_stream_encoder,
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200214 RtcEventLog* event_log,
215 const VideoSendStream::Config* config,
216 int initial_encoder_max_bitrate,
217 double initial_encoder_bitrate_priority,
218 std::map<uint32_t, RtpState> suspended_ssrcs,
219 std::map<uint32_t, RtpPayloadState> suspended_payload_states,
220 VideoEncoderConfig::ContentType content_type,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200221 std::unique_ptr<FecController> fec_controller)
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200222 : has_alr_probing_(config->periodic_alr_bandwidth_probing ||
Erik Språngb57ab382018-09-13 10:52:38 +0200223 GetAlrSettings(content_type)),
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200224 stats_proxy_(stats_proxy),
225 config_(config),
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200226 worker_queue_(worker_queue),
227 check_encoder_activity_task_(nullptr),
228 call_stats_(call_stats),
229 transport_(transport),
230 bitrate_allocator_(bitrate_allocator),
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200231 max_padding_bitrate_(0),
232 encoder_min_bitrate_bps_(0),
233 encoder_target_rate_bps_(0),
234 encoder_bitrate_priority_(initial_encoder_bitrate_priority),
235 has_packet_feedback_(false),
236 video_stream_encoder_(video_stream_encoder),
237 encoder_feedback_(Clock::GetRealTimeClock(),
238 config_->rtp.ssrcs,
239 video_stream_encoder),
240 bandwidth_observer_(transport->GetBandwidthObserver()),
Stefan Holmer9416ef82018-07-19 10:34:38 +0200241 rtp_video_sender_(
242 transport_->CreateRtpVideoSender(config_->rtp.ssrcs,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200243 suspended_ssrcs,
244 suspended_payload_states,
245 config_->rtp,
246 config_->rtcp,
247 config_->send_transport,
248 CreateObservers(call_stats,
249 &encoder_feedback_,
250 stats_proxy_,
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200251 send_delay_stats),
252 event_log,
253 std::move(fec_controller))),
254 weak_ptr_factory_(this) {
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200255 RTC_DCHECK_RUN_ON(worker_queue_);
256 RTC_LOG(LS_INFO) << "VideoSendStreamInternal: " << config_->ToString();
257 weak_ptr_ = weak_ptr_factory_.GetWeakPtr();
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200258
259 RTC_DCHECK(!config_->rtp.ssrcs.empty());
260 RTC_DCHECK(call_stats_);
261 RTC_DCHECK(transport_);
262 RTC_DCHECK_NE(initial_encoder_max_bitrate, 0);
263
264 if (initial_encoder_max_bitrate > 0) {
265 encoder_max_bitrate_bps_ =
266 rtc::dchecked_cast<uint32_t>(initial_encoder_max_bitrate);
267 } else {
268 // TODO(srte): Make sure max bitrate is not set to negative values. We don't
269 // have any way to handle unset values in downstream code, such as the
270 // bitrate allocator. Previously -1 was implicitly casted to UINT32_MAX, a
271 // behaviour that is not safe. Converting to 10 Mbps should be safe for
272 // reasonable use cases as it allows adding the max of multiple streams
273 // without wrappping around.
274 const int kFallbackMaxBitrateBps = 10000000;
275 RTC_DLOG(LS_ERROR) << "ERROR: Initial encoder max bitrate = "
276 << initial_encoder_max_bitrate << " which is <= 0!";
277 RTC_DLOG(LS_INFO) << "Using default encoder max bitrate = 10 Mbps";
278 encoder_max_bitrate_bps_ = kFallbackMaxBitrateBps;
279 }
280
281 RTC_CHECK(AlrExperimentSettings::MaxOneFieldTrialEnabled());
282 // If send-side BWE is enabled, check if we should apply updated probing and
283 // pacing settings.
284 if (TransportSeqNumExtensionConfigured(*config_)) {
285 has_packet_feedback_ = true;
286
Erik Språngb57ab382018-09-13 10:52:38 +0200287 absl::optional<AlrExperimentSettings> alr_settings =
288 GetAlrSettings(content_type);
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200289 if (alr_settings) {
290 transport->EnablePeriodicAlrProbing(true);
291 transport->SetPacingFactor(alr_settings->pacing_factor);
292 configured_pacing_factor_ = alr_settings->pacing_factor;
293 transport->SetQueueTimeLimit(alr_settings->max_paced_queue_time);
294 } else {
295 transport->EnablePeriodicAlrProbing(false);
296 transport->SetPacingFactor(PacedSender::kDefaultPaceMultiplier);
297 configured_pacing_factor_ = PacedSender::kDefaultPaceMultiplier;
298 transport->SetQueueTimeLimit(PacedSender::kMaxQueueLengthMs);
299 }
300 }
301
302 if (config_->periodic_alr_bandwidth_probing) {
303 transport->EnablePeriodicAlrProbing(true);
304 }
305
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200306 RTC_DCHECK_GE(config_->rtp.payload_type, 0);
307 RTC_DCHECK_LE(config_->rtp.payload_type, 127);
308
309 video_stream_encoder_->SetStartBitrate(
310 bitrate_allocator_->GetStartBitrate(this));
311
312 // Only request rotation at the source when we positively know that the remote
313 // side doesn't support the rotation extension. This allows us to prepare the
314 // encoder in the expectation that rotation is supported - which is the common
315 // case.
316 bool rotation_applied =
317 std::find_if(config_->rtp.extensions.begin(),
318 config_->rtp.extensions.end(),
319 [](const RtpExtension& extension) {
320 return extension.uri == RtpExtension::kVideoRotationUri;
321 }) == config_->rtp.extensions.end();
322
323 video_stream_encoder_->SetSink(this, rotation_applied);
324}
325
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200326VideoSendStreamImpl::~VideoSendStreamImpl() {
327 RTC_DCHECK_RUN_ON(worker_queue_);
Stefan Holmer9416ef82018-07-19 10:34:38 +0200328 RTC_DCHECK(!rtp_video_sender_->IsActive())
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200329 << "VideoSendStreamImpl::Stop not called";
330 RTC_LOG(LS_INFO) << "~VideoSendStreamInternal: " << config_->ToString();
Stefan Holmer9416ef82018-07-19 10:34:38 +0200331 transport_->DestroyRtpVideoSender(rtp_video_sender_);
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200332}
333
334void VideoSendStreamImpl::RegisterProcessThread(
335 ProcessThread* module_process_thread) {
Stefan Holmer9416ef82018-07-19 10:34:38 +0200336 rtp_video_sender_->RegisterProcessThread(module_process_thread);
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200337}
338
339void VideoSendStreamImpl::DeRegisterProcessThread() {
Stefan Holmer9416ef82018-07-19 10:34:38 +0200340 rtp_video_sender_->DeRegisterProcessThread();
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200341}
342
343bool VideoSendStreamImpl::DeliverRtcp(const uint8_t* packet, size_t length) {
344 // Runs on a network thread.
345 RTC_DCHECK(!worker_queue_->IsCurrent());
Stefan Holmer9416ef82018-07-19 10:34:38 +0200346 rtp_video_sender_->DeliverRtcp(packet, length);
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200347 return true;
348}
349
350void VideoSendStreamImpl::UpdateActiveSimulcastLayers(
351 const std::vector<bool> active_layers) {
352 RTC_DCHECK_RUN_ON(worker_queue_);
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200353 RTC_LOG(LS_INFO) << "VideoSendStream::UpdateActiveSimulcastLayers";
Stefan Holmer9416ef82018-07-19 10:34:38 +0200354 bool previously_active = rtp_video_sender_->IsActive();
355 rtp_video_sender_->SetActiveModules(active_layers);
356 if (!rtp_video_sender_->IsActive() && previously_active) {
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200357 // Payload router switched from active to inactive.
358 StopVideoSendStream();
Stefan Holmer9416ef82018-07-19 10:34:38 +0200359 } else if (rtp_video_sender_->IsActive() && !previously_active) {
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200360 // Payload router switched from inactive to active.
361 StartupVideoSendStream();
362 }
363}
364
365void VideoSendStreamImpl::Start() {
366 RTC_DCHECK_RUN_ON(worker_queue_);
367 RTC_LOG(LS_INFO) << "VideoSendStream::Start";
Stefan Holmer9416ef82018-07-19 10:34:38 +0200368 if (rtp_video_sender_->IsActive())
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200369 return;
370 TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Start");
Stefan Holmer9416ef82018-07-19 10:34:38 +0200371 rtp_video_sender_->SetActive(true);
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200372 StartupVideoSendStream();
373}
374
375void VideoSendStreamImpl::StartupVideoSendStream() {
376 RTC_DCHECK_RUN_ON(worker_queue_);
377 bitrate_allocator_->AddObserver(
Sebastian Jansson24ad7202018-04-19 08:25:12 +0200378 this,
379 MediaStreamAllocationConfig{
380 static_cast<uint32_t>(encoder_min_bitrate_bps_),
381 encoder_max_bitrate_bps_, static_cast<uint32_t>(max_padding_bitrate_),
382 !config_->suspend_below_min_bitrate, config_->track_id,
383 encoder_bitrate_priority_, has_packet_feedback_});
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200384 // Start monitoring encoder activity.
385 {
386 rtc::CritScope lock(&encoder_activity_crit_sect_);
387 RTC_DCHECK(!check_encoder_activity_task_);
388 check_encoder_activity_task_ = new CheckEncoderActivityTask(weak_ptr_);
389 worker_queue_->PostDelayedTask(
390 std::unique_ptr<rtc::QueuedTask>(check_encoder_activity_task_),
391 CheckEncoderActivityTask::kEncoderTimeOutMs);
392 }
393
394 video_stream_encoder_->SendKeyFrame();
395}
396
397void VideoSendStreamImpl::Stop() {
398 RTC_DCHECK_RUN_ON(worker_queue_);
399 RTC_LOG(LS_INFO) << "VideoSendStream::Stop";
Stefan Holmer9416ef82018-07-19 10:34:38 +0200400 if (!rtp_video_sender_->IsActive())
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200401 return;
402 TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Stop");
Stefan Holmer9416ef82018-07-19 10:34:38 +0200403 rtp_video_sender_->SetActive(false);
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200404 StopVideoSendStream();
405}
406
407void VideoSendStreamImpl::StopVideoSendStream() {
408 bitrate_allocator_->RemoveObserver(this);
409 {
410 rtc::CritScope lock(&encoder_activity_crit_sect_);
411 check_encoder_activity_task_->Stop();
412 check_encoder_activity_task_ = nullptr;
413 }
414 video_stream_encoder_->OnBitrateUpdated(0, 0, 0);
415 stats_proxy_->OnSetEncoderTargetRate(0);
416}
417
418void VideoSendStreamImpl::SignalEncoderTimedOut() {
419 RTC_DCHECK_RUN_ON(worker_queue_);
420 // If the encoder has not produced anything the last kEncoderTimeOutMs and it
421 // is supposed to, deregister as BitrateAllocatorObserver. This can happen
422 // if a camera stops producing frames.
423 if (encoder_target_rate_bps_ > 0) {
424 RTC_LOG(LS_INFO) << "SignalEncoderTimedOut, Encoder timed out.";
425 bitrate_allocator_->RemoveObserver(this);
426 }
427}
428
429void VideoSendStreamImpl::OnBitrateAllocationUpdated(
Erik Språng566124a2018-04-23 12:32:22 +0200430 const VideoBitrateAllocation& allocation) {
Erik Språng4e193e42018-09-14 19:01:58 +0200431 if (!worker_queue_->IsCurrent()) {
432 auto ptr = weak_ptr_;
433 worker_queue_->PostTask([=] {
434 if (!ptr.get())
435 return;
436 ptr->OnBitrateAllocationUpdated(allocation);
437 });
438 return;
439 }
440
441 RTC_DCHECK_RUN_ON(worker_queue_);
442
443 int64_t now_ms = rtc::TimeMillis();
Erik Språngf4ef2dd2018-09-11 12:37:51 +0200444 if (encoder_target_rate_bps_ != 0) {
Erik Språng4e193e42018-09-14 19:01:58 +0200445 if (video_bitrate_allocation_context_) {
446 // If new allocation is within kMaxVbaSizeDifferencePercent larger than
447 // the previously sent allocation and the same streams are still enabled,
448 // it is considered "similar". We do not want send similar allocations
449 // more once per kMaxVbaThrottleTimeMs.
450 const VideoBitrateAllocation& last =
451 video_bitrate_allocation_context_->last_sent_allocation;
452 const bool is_similar =
453 allocation.get_sum_bps() >= last.get_sum_bps() &&
454 allocation.get_sum_bps() <
455 (last.get_sum_bps() * (100 + kMaxVbaSizeDifferencePercent)) /
456 100 &&
457 SameStreamsEnabled(allocation, last);
458 if (is_similar &&
459 (now_ms - video_bitrate_allocation_context_->last_send_time_ms) <
460 kMaxVbaThrottleTimeMs) {
461 // This allocation is too similar, cache it and return.
462 video_bitrate_allocation_context_->throttled_allocation = allocation;
463 return;
464 }
465 } else {
466 video_bitrate_allocation_context_.emplace();
467 }
468
469 video_bitrate_allocation_context_->last_sent_allocation = allocation;
470 video_bitrate_allocation_context_->throttled_allocation.reset();
471 video_bitrate_allocation_context_->last_send_time_ms = now_ms;
472
Erik Språngf4ef2dd2018-09-11 12:37:51 +0200473 // Send bitrate allocation metadata only if encoder is not paused.
474 rtp_video_sender_->OnBitrateAllocationUpdated(allocation);
475 }
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200476}
477
478void VideoSendStreamImpl::SignalEncoderActive() {
479 RTC_DCHECK_RUN_ON(worker_queue_);
480 RTC_LOG(LS_INFO) << "SignalEncoderActive, Encoder is active.";
481 bitrate_allocator_->AddObserver(
Sebastian Jansson24ad7202018-04-19 08:25:12 +0200482 this,
483 MediaStreamAllocationConfig{
484 static_cast<uint32_t>(encoder_min_bitrate_bps_),
485 encoder_max_bitrate_bps_, static_cast<uint32_t>(max_padding_bitrate_),
486 !config_->suspend_below_min_bitrate, config_->track_id,
487 encoder_bitrate_priority_, has_packet_feedback_});
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200488}
489
490void VideoSendStreamImpl::OnEncoderConfigurationChanged(
491 std::vector<VideoStream> streams,
492 int min_transmit_bitrate_bps) {
493 if (!worker_queue_->IsCurrent()) {
494 rtc::WeakPtr<VideoSendStreamImpl> send_stream = weak_ptr_;
495 worker_queue_->PostTask([send_stream, streams, min_transmit_bitrate_bps]() {
496 if (send_stream)
497 send_stream->OnEncoderConfigurationChanged(std::move(streams),
498 min_transmit_bitrate_bps);
499 });
500 return;
501 }
502 RTC_DCHECK_GE(config_->rtp.ssrcs.size(), streams.size());
503 TRACE_EVENT0("webrtc", "VideoSendStream::OnEncoderConfigurationChanged");
504 RTC_DCHECK_GE(config_->rtp.ssrcs.size(), streams.size());
505 RTC_DCHECK_RUN_ON(worker_queue_);
506
507 encoder_min_bitrate_bps_ =
508 std::max(streams[0].min_bitrate_bps, GetEncoderMinBitrateBps());
509 encoder_max_bitrate_bps_ = 0;
510 double stream_bitrate_priority_sum = 0;
511 for (const auto& stream : streams) {
512 // We don't want to allocate more bitrate than needed to inactive streams.
513 encoder_max_bitrate_bps_ += stream.active ? stream.max_bitrate_bps : 0;
514 if (stream.bitrate_priority) {
515 RTC_DCHECK_GT(*stream.bitrate_priority, 0);
516 stream_bitrate_priority_sum += *stream.bitrate_priority;
517 }
518 }
519 RTC_DCHECK_GT(stream_bitrate_priority_sum, 0);
520 encoder_bitrate_priority_ = stream_bitrate_priority_sum;
521 encoder_max_bitrate_bps_ =
522 std::max(static_cast<uint32_t>(encoder_min_bitrate_bps_),
523 encoder_max_bitrate_bps_);
“Michael277a6562018-06-01 14:09:19 -0500524
525 const VideoCodecType codec_type =
526 PayloadStringToCodecType(config_->rtp.payload_name);
527 if (codec_type == kVideoCodecVP9) {
528 max_padding_bitrate_ = streams[0].target_bitrate_bps;
529 } else {
530 max_padding_bitrate_ = CalculateMaxPadBitrateBps(
Erik Språngb57ab382018-09-13 10:52:38 +0200531 streams, min_transmit_bitrate_bps, config_->suspend_below_min_bitrate,
532 has_alr_probing_);
“Michael277a6562018-06-01 14:09:19 -0500533 }
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200534
535 // Clear stats for disabled layers.
536 for (size_t i = streams.size(); i < config_->rtp.ssrcs.size(); ++i) {
537 stats_proxy_->OnInactiveSsrc(config_->rtp.ssrcs[i]);
538 }
539
540 const size_t num_temporal_layers =
541 streams.back().num_temporal_layers.value_or(1);
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200542
543 rtp_video_sender_->SetEncodingData(streams[0].width, streams[0].height,
544 num_temporal_layers);
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200545
Stefan Holmer9416ef82018-07-19 10:34:38 +0200546 if (rtp_video_sender_->IsActive()) {
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200547 // The send stream is started already. Update the allocator with new bitrate
548 // limits.
549 bitrate_allocator_->AddObserver(
Sebastian Jansson24ad7202018-04-19 08:25:12 +0200550 this, MediaStreamAllocationConfig{
551 static_cast<uint32_t>(encoder_min_bitrate_bps_),
552 encoder_max_bitrate_bps_,
553 static_cast<uint32_t>(max_padding_bitrate_),
554 !config_->suspend_below_min_bitrate, config_->track_id,
555 encoder_bitrate_priority_, has_packet_feedback_});
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200556 }
557}
558
559EncodedImageCallback::Result VideoSendStreamImpl::OnEncodedImage(
560 const EncodedImage& encoded_image,
561 const CodecSpecificInfo* codec_specific_info,
562 const RTPFragmentationHeader* fragmentation) {
563 // Encoded is called on whatever thread the real encoder implementation run
564 // on. In the case of hardware encoders, there might be several encoders
565 // running in parallel on different threads.
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200566 {
567 rtc::CritScope lock(&encoder_activity_crit_sect_);
568 if (check_encoder_activity_task_)
569 check_encoder_activity_task_->UpdateEncoderActivity();
570 }
571
Erik Språng4e193e42018-09-14 19:01:58 +0200572 EncodedImageCallback::Result result = rtp_video_sender_->OnEncodedImage(
573 encoded_image, codec_specific_info, fragmentation);
574
575 // Check if there's a throttled VideoBitrateAllocation that we should try
576 // sending.
577 rtc::WeakPtr<VideoSendStreamImpl> send_stream = weak_ptr_;
578 auto update_task = [send_stream]() {
579 if (send_stream) {
580 RTC_DCHECK_RUN_ON(send_stream->worker_queue_);
581 auto& context = send_stream->video_bitrate_allocation_context_;
582 if (context && context->throttled_allocation) {
583 send_stream->OnBitrateAllocationUpdated(*context->throttled_allocation);
584 }
585 }
586 };
587 if (!worker_queue_->IsCurrent()) {
588 worker_queue_->PostTask(update_task);
589 } else {
590 update_task();
591 }
592
593 return result;
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200594}
595
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200596std::map<uint32_t, RtpState> VideoSendStreamImpl::GetRtpStates() const {
Stefan Holmer9416ef82018-07-19 10:34:38 +0200597 return rtp_video_sender_->GetRtpStates();
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200598}
599
600std::map<uint32_t, RtpPayloadState> VideoSendStreamImpl::GetRtpPayloadStates()
601 const {
Stefan Holmer9416ef82018-07-19 10:34:38 +0200602 return rtp_video_sender_->GetRtpPayloadStates();
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200603}
604
605uint32_t VideoSendStreamImpl::OnBitrateUpdated(uint32_t bitrate_bps,
606 uint8_t fraction_loss,
607 int64_t rtt,
608 int64_t probing_interval_ms) {
609 RTC_DCHECK_RUN_ON(worker_queue_);
Stefan Holmer9416ef82018-07-19 10:34:38 +0200610 RTC_DCHECK(rtp_video_sender_->IsActive())
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200611 << "VideoSendStream::Start has not been called.";
612
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200613 rtp_video_sender_->OnBitrateUpdated(bitrate_bps, fraction_loss, rtt,
614 stats_proxy_->GetSendFrameRate());
615 encoder_target_rate_bps_ = rtp_video_sender_->GetPayloadBitrateBps();
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200616 encoder_target_rate_bps_ =
617 std::min(encoder_max_bitrate_bps_, encoder_target_rate_bps_);
618 video_stream_encoder_->OnBitrateUpdated(encoder_target_rate_bps_,
619 fraction_loss, rtt);
620 stats_proxy_->OnSetEncoderTargetRate(encoder_target_rate_bps_);
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200621 return rtp_video_sender_->GetProtectionBitrateBps();
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200622}
623
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200624} // namespace internal
625} // namespace webrtc