blob: 563555044f76c475cd199d64e65a6c836f893a1c [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
Yves Gerey3e707812018-11-28 16:47:49 +010012#include <stdio.h>
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +020013#include <algorithm>
Yves Gerey3e707812018-11-28 16:47:49 +010014#include <cstdint>
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +020015#include <string>
16#include <utility>
17
Steve Anton10542f22019-01-11 09:11:00 -080018#include "api/crypto/crypto_options.h"
19#include "api/rtp_parameters.h"
Mirko Bonadeid9708072019-01-25 20:26:48 +010020#include "api/scoped_refptr.h"
Yves Gerey3e707812018-11-28 16:47:49 +010021#include "api/video_codecs/video_codec.h"
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +020022#include "call/rtp_transport_controller_send_interface.h"
Yves Gerey3e707812018-11-28 16:47:49 +010023#include "call/video_send_stream.h"
24#include "common_types.h" // NOLINT(build/include)
25#include "modules/pacing/paced_sender.h"
Steve Anton10542f22019-01-11 09:11:00 -080026#include "rtc_base/atomic_ops.h"
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +020027#include "rtc_base/checks.h"
28#include "rtc_base/experiments/alr_experiment.h"
Erik Språngcd76eab2019-01-21 18:06:46 +010029#include "rtc_base/experiments/rate_control_settings.h"
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +020030#include "rtc_base/logging.h"
31#include "rtc_base/numerics/safe_conversions.h"
Yves Gerey3e707812018-11-28 16:47:49 +010032#include "rtc_base/sequenced_task_checker.h"
33#include "rtc_base/thread_checker.h"
Steve Anton10542f22019-01-11 09:11:00 -080034#include "rtc_base/time_utils.h"
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +020035#include "rtc_base/trace_event.h"
Yves Gerey3e707812018-11-28 16:47:49 +010036#include "system_wrappers/include/clock.h"
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +020037#include "system_wrappers/include/field_trial.h"
38
39namespace webrtc {
40namespace internal {
41namespace {
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +020042
Erik Språng4e193e42018-09-14 19:01:58 +020043// Max positive size difference to treat allocations as "similar".
44static constexpr int kMaxVbaSizeDifferencePercent = 10;
45// Max time we will throttle similar video bitrate allocations.
46static constexpr int64_t kMaxVbaThrottleTimeMs = 500;
47
Sebastian Janssonecb68972019-01-18 10:30:54 +010048constexpr TimeDelta kEncoderTimeOut = TimeDelta::Seconds<2>();
49
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +020050bool TransportSeqNumExtensionConfigured(const VideoSendStream::Config& config) {
51 const std::vector<RtpExtension>& extensions = config.rtp.extensions;
52 return std::find_if(
53 extensions.begin(), extensions.end(), [](const RtpExtension& ext) {
54 return ext.uri == RtpExtension::kTransportSequenceNumberUri;
55 }) != extensions.end();
56}
57
58const char kForcedFallbackFieldTrial[] =
59 "WebRTC-VP8-Forced-Fallback-Encoder-v2";
60
Danil Chapovalovb9b146c2018-06-15 12:28:07 +020061absl::optional<int> GetFallbackMinBpsFromFieldTrial() {
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +020062 if (!webrtc::field_trial::IsEnabled(kForcedFallbackFieldTrial))
Danil Chapovalovb9b146c2018-06-15 12:28:07 +020063 return absl::nullopt;
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +020064
65 std::string group =
66 webrtc::field_trial::FindFullName(kForcedFallbackFieldTrial);
67 if (group.empty())
Danil Chapovalovb9b146c2018-06-15 12:28:07 +020068 return absl::nullopt;
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +020069
70 int min_pixels;
71 int max_pixels;
72 int min_bps;
73 if (sscanf(group.c_str(), "Enabled-%d,%d,%d", &min_pixels, &max_pixels,
74 &min_bps) != 3) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +020075 return absl::nullopt;
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +020076 }
77
78 if (min_bps <= 0)
Danil Chapovalovb9b146c2018-06-15 12:28:07 +020079 return absl::nullopt;
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +020080
81 return min_bps;
82}
83
84int GetEncoderMinBitrateBps() {
85 const int kDefaultEncoderMinBitrateBps = 30000;
86 return GetFallbackMinBpsFromFieldTrial().value_or(
87 kDefaultEncoderMinBitrateBps);
88}
89
Erik Språngb57ab382018-09-13 10:52:38 +020090// Calculate max padding bitrate for a multi layer codec.
91int CalculateMaxPadBitrateBps(const std::vector<VideoStream>& streams,
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +020092 int min_transmit_bitrate_bps,
Erik Språngb57ab382018-09-13 10:52:38 +020093 bool pad_to_min_bitrate,
94 bool alr_probing) {
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +020095 int pad_up_to_bitrate_bps = 0;
Erik Språngb57ab382018-09-13 10:52:38 +020096
97 // Filter out only the active streams;
98 std::vector<VideoStream> active_streams;
99 for (const VideoStream& stream : streams) {
100 if (stream.active)
101 active_streams.emplace_back(stream);
102 }
103
104 if (active_streams.size() > 1) {
105 if (alr_probing) {
106 // With alr probing, just pad to the min bitrate of the lowest stream,
107 // probing will handle the rest of the rampup.
108 pad_up_to_bitrate_bps = active_streams[0].min_bitrate_bps;
109 } else {
110 // Pad to min bitrate of the highest layer.
111 pad_up_to_bitrate_bps =
112 active_streams[active_streams.size() - 1].min_bitrate_bps;
113 // Add target_bitrate_bps of the lower layers.
114 for (size_t i = 0; i < active_streams.size() - 1; ++i)
115 pad_up_to_bitrate_bps += active_streams[i].target_bitrate_bps;
116 }
117 } else if (!active_streams.empty() && pad_to_min_bitrate) {
118 pad_up_to_bitrate_bps = active_streams[0].min_bitrate_bps;
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200119 }
120
121 pad_up_to_bitrate_bps =
122 std::max(pad_up_to_bitrate_bps, min_transmit_bitrate_bps);
123
124 return pad_up_to_bitrate_bps;
125}
126
Benjamin Wright192eeec2018-10-17 17:27:25 -0700127RtpSenderFrameEncryptionConfig CreateFrameEncryptionConfig(
128 const VideoSendStream::Config* config) {
129 RtpSenderFrameEncryptionConfig frame_encryption_config;
130 frame_encryption_config.frame_encryptor = config->frame_encryptor;
131 frame_encryption_config.crypto_options = config->crypto_options;
132 return frame_encryption_config;
133}
134
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200135RtpSenderObservers CreateObservers(CallStats* call_stats,
Niels Möllerfa89d842019-01-30 16:33:45 +0100136 EncoderKeyFrameCallback* encoder_feedback,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200137 SendStatisticsProxy* stats_proxy,
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200138 SendDelayStats* send_delay_stats) {
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200139 RtpSenderObservers observers;
140 observers.rtcp_rtt_stats = call_stats;
141 observers.intra_frame_callback = encoder_feedback;
142 observers.rtcp_stats = stats_proxy;
143 observers.rtp_stats = stats_proxy;
144 observers.bitrate_observer = stats_proxy;
145 observers.frame_count_observer = stats_proxy;
146 observers.rtcp_type_observer = stats_proxy;
147 observers.send_delay_observer = stats_proxy;
148 observers.send_packet_observer = send_delay_stats;
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200149 return observers;
150}
Erik Språngb57ab382018-09-13 10:52:38 +0200151
152absl::optional<AlrExperimentSettings> GetAlrSettings(
153 VideoEncoderConfig::ContentType content_type) {
154 if (content_type == VideoEncoderConfig::ContentType::kScreen) {
155 return AlrExperimentSettings::CreateFromFieldTrial(
156 AlrExperimentSettings::kScreenshareProbingBweExperimentName);
157 }
158 return AlrExperimentSettings::CreateFromFieldTrial(
159 AlrExperimentSettings::kStrictPacingAndProbingExperimentName);
160}
Erik Språng4e193e42018-09-14 19:01:58 +0200161
162bool SameStreamsEnabled(const VideoBitrateAllocation& lhs,
163 const VideoBitrateAllocation& rhs) {
164 for (size_t si = 0; si < kMaxSpatialLayers; ++si) {
165 for (size_t ti = 0; ti < kMaxTemporalStreams; ++ti) {
166 if (lhs.HasBitrate(si, ti) != rhs.HasBitrate(si, ti)) {
167 return false;
168 }
169 }
170 }
171 return true;
172}
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200173} // namespace
174
Christoffer Rodbro196c5ba2018-11-27 11:56:25 +0100175PacingConfig::PacingConfig()
176 : pacing_factor("factor", PacedSender::kDefaultPaceMultiplier),
177 max_pacing_delay("max_delay",
178 TimeDelta::ms(PacedSender::kMaxQueueLengthMs)) {
179 ParseFieldTrial({&pacing_factor, &max_pacing_delay},
180 field_trial::FindFullName("WebRTC-Video-Pacing"));
181}
182PacingConfig::PacingConfig(const PacingConfig&) = default;
183PacingConfig::~PacingConfig() = default;
184
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200185VideoSendStreamImpl::VideoSendStreamImpl(
186 SendStatisticsProxy* stats_proxy,
187 rtc::TaskQueue* worker_queue,
188 CallStats* call_stats,
189 RtpTransportControllerSendInterface* transport,
Sebastian Jansson652dc912018-04-19 17:09:15 +0200190 BitrateAllocatorInterface* bitrate_allocator,
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200191 SendDelayStats* send_delay_stats,
Sebastian Jansson652dc912018-04-19 17:09:15 +0200192 VideoStreamEncoderInterface* video_stream_encoder,
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200193 RtcEventLog* event_log,
194 const VideoSendStream::Config* config,
195 int initial_encoder_max_bitrate,
196 double initial_encoder_bitrate_priority,
197 std::map<uint32_t, RtpState> suspended_ssrcs,
198 std::map<uint32_t, RtpPayloadState> suspended_payload_states,
199 VideoEncoderConfig::ContentType content_type,
Niels Möller46879152019-01-07 15:54:47 +0100200 std::unique_ptr<FecController> fec_controller,
201 MediaTransportInterface* media_transport)
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200202 : has_alr_probing_(config->periodic_alr_bandwidth_probing ||
Erik Språngb57ab382018-09-13 10:52:38 +0200203 GetAlrSettings(content_type)),
Christoffer Rodbro196c5ba2018-11-27 11:56:25 +0100204 pacing_config_(PacingConfig()),
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200205 stats_proxy_(stats_proxy),
206 config_(config),
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200207 worker_queue_(worker_queue),
Erik Språngcd76eab2019-01-21 18:06:46 +0100208 timed_out_(false),
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200209 call_stats_(call_stats),
210 transport_(transport),
211 bitrate_allocator_(bitrate_allocator),
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200212 max_padding_bitrate_(0),
213 encoder_min_bitrate_bps_(0),
214 encoder_target_rate_bps_(0),
215 encoder_bitrate_priority_(initial_encoder_bitrate_priority),
216 has_packet_feedback_(false),
217 video_stream_encoder_(video_stream_encoder),
218 encoder_feedback_(Clock::GetRealTimeClock(),
219 config_->rtp.ssrcs,
220 video_stream_encoder),
221 bandwidth_observer_(transport->GetBandwidthObserver()),
Benjamin Wright192eeec2018-10-17 17:27:25 -0700222 rtp_video_sender_(transport_->CreateRtpVideoSender(
Benjamin Wright192eeec2018-10-17 17:27:25 -0700223 suspended_ssrcs,
224 suspended_payload_states,
225 config_->rtp,
Jiawei Ou55718122018-11-09 13:17:39 -0800226 config_->rtcp_report_interval_ms,
Benjamin Wright192eeec2018-10-17 17:27:25 -0700227 config_->send_transport,
228 CreateObservers(call_stats,
229 &encoder_feedback_,
230 stats_proxy_,
231 send_delay_stats),
232 event_log,
233 std::move(fec_controller),
234 CreateFrameEncryptionConfig(config_))),
Niels Möller46879152019-01-07 15:54:47 +0100235 weak_ptr_factory_(this),
236 media_transport_(media_transport) {
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200237 RTC_DCHECK_RUN_ON(worker_queue_);
238 RTC_LOG(LS_INFO) << "VideoSendStreamInternal: " << config_->ToString();
239 weak_ptr_ = weak_ptr_factory_.GetWeakPtr();
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200240
Niels Möller46879152019-01-07 15:54:47 +0100241 if (media_transport_) {
242 // The configured ssrc is interpreted as a channel id, so there must be
243 // exactly one.
244 RTC_DCHECK_EQ(config_->rtp.ssrcs.size(), 1);
Niels Möllerfa89d842019-01-30 16:33:45 +0100245 media_transport_->SetKeyFrameRequestCallback(&encoder_feedback_);
Niels Möller46879152019-01-07 15:54:47 +0100246 } else {
247 RTC_DCHECK(!config_->rtp.ssrcs.empty());
248 }
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200249 RTC_DCHECK(call_stats_);
250 RTC_DCHECK(transport_);
251 RTC_DCHECK_NE(initial_encoder_max_bitrate, 0);
252
253 if (initial_encoder_max_bitrate > 0) {
254 encoder_max_bitrate_bps_ =
255 rtc::dchecked_cast<uint32_t>(initial_encoder_max_bitrate);
256 } else {
257 // TODO(srte): Make sure max bitrate is not set to negative values. We don't
258 // have any way to handle unset values in downstream code, such as the
259 // bitrate allocator. Previously -1 was implicitly casted to UINT32_MAX, a
260 // behaviour that is not safe. Converting to 10 Mbps should be safe for
261 // reasonable use cases as it allows adding the max of multiple streams
262 // without wrappping around.
263 const int kFallbackMaxBitrateBps = 10000000;
264 RTC_DLOG(LS_ERROR) << "ERROR: Initial encoder max bitrate = "
265 << initial_encoder_max_bitrate << " which is <= 0!";
266 RTC_DLOG(LS_INFO) << "Using default encoder max bitrate = 10 Mbps";
267 encoder_max_bitrate_bps_ = kFallbackMaxBitrateBps;
268 }
269
270 RTC_CHECK(AlrExperimentSettings::MaxOneFieldTrialEnabled());
271 // If send-side BWE is enabled, check if we should apply updated probing and
272 // pacing settings.
273 if (TransportSeqNumExtensionConfigured(*config_)) {
274 has_packet_feedback_ = true;
275
Erik Språngb57ab382018-09-13 10:52:38 +0200276 absl::optional<AlrExperimentSettings> alr_settings =
277 GetAlrSettings(content_type);
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200278 if (alr_settings) {
279 transport->EnablePeriodicAlrProbing(true);
280 transport->SetPacingFactor(alr_settings->pacing_factor);
281 configured_pacing_factor_ = alr_settings->pacing_factor;
282 transport->SetQueueTimeLimit(alr_settings->max_paced_queue_time);
283 } else {
Erik Språngcd76eab2019-01-21 18:06:46 +0100284 RateControlSettings rate_control_settings =
285 RateControlSettings::ParseFromFieldTrials();
286
287 transport->EnablePeriodicAlrProbing(
288 rate_control_settings.UseAlrProbing());
289 const double pacing_factor =
290 rate_control_settings.GetPacingFactor().value_or(
291 pacing_config_.pacing_factor);
292 transport->SetPacingFactor(pacing_factor);
293 configured_pacing_factor_ = pacing_factor;
Christoffer Rodbro196c5ba2018-11-27 11:56:25 +0100294 transport->SetQueueTimeLimit(pacing_config_.max_pacing_delay.Get().ms());
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200295 }
296 }
297
298 if (config_->periodic_alr_bandwidth_probing) {
299 transport->EnablePeriodicAlrProbing(true);
300 }
301
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200302 RTC_DCHECK_GE(config_->rtp.payload_type, 0);
303 RTC_DCHECK_LE(config_->rtp.payload_type, 127);
304
305 video_stream_encoder_->SetStartBitrate(
306 bitrate_allocator_->GetStartBitrate(this));
307
308 // Only request rotation at the source when we positively know that the remote
309 // side doesn't support the rotation extension. This allows us to prepare the
310 // encoder in the expectation that rotation is supported - which is the common
311 // case.
312 bool rotation_applied =
313 std::find_if(config_->rtp.extensions.begin(),
314 config_->rtp.extensions.end(),
315 [](const RtpExtension& extension) {
316 return extension.uri == RtpExtension::kVideoRotationUri;
317 }) == config_->rtp.extensions.end();
318
319 video_stream_encoder_->SetSink(this, rotation_applied);
320}
321
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200322VideoSendStreamImpl::~VideoSendStreamImpl() {
323 RTC_DCHECK_RUN_ON(worker_queue_);
Stefan Holmer9416ef82018-07-19 10:34:38 +0200324 RTC_DCHECK(!rtp_video_sender_->IsActive())
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200325 << "VideoSendStreamImpl::Stop not called";
326 RTC_LOG(LS_INFO) << "~VideoSendStreamInternal: " << config_->ToString();
Stefan Holmer9416ef82018-07-19 10:34:38 +0200327 transport_->DestroyRtpVideoSender(rtp_video_sender_);
Niels Möllerfa89d842019-01-30 16:33:45 +0100328 if (media_transport_) {
329 media_transport_->SetKeyFrameRequestCallback(nullptr);
330 }
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200331}
332
333void VideoSendStreamImpl::RegisterProcessThread(
334 ProcessThread* module_process_thread) {
Stefan Holmer9416ef82018-07-19 10:34:38 +0200335 rtp_video_sender_->RegisterProcessThread(module_process_thread);
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200336}
337
338void VideoSendStreamImpl::DeRegisterProcessThread() {
Stefan Holmer9416ef82018-07-19 10:34:38 +0200339 rtp_video_sender_->DeRegisterProcessThread();
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200340}
341
342bool VideoSendStreamImpl::DeliverRtcp(const uint8_t* packet, size_t length) {
343 // Runs on a network thread.
344 RTC_DCHECK(!worker_queue_->IsCurrent());
Stefan Holmer9416ef82018-07-19 10:34:38 +0200345 rtp_video_sender_->DeliverRtcp(packet, length);
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200346 return true;
347}
348
349void VideoSendStreamImpl::UpdateActiveSimulcastLayers(
350 const std::vector<bool> active_layers) {
351 RTC_DCHECK_RUN_ON(worker_queue_);
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200352 RTC_LOG(LS_INFO) << "VideoSendStream::UpdateActiveSimulcastLayers";
Stefan Holmer9416ef82018-07-19 10:34:38 +0200353 bool previously_active = rtp_video_sender_->IsActive();
354 rtp_video_sender_->SetActiveModules(active_layers);
355 if (!rtp_video_sender_->IsActive() && previously_active) {
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200356 // Payload router switched from active to inactive.
357 StopVideoSendStream();
Stefan Holmer9416ef82018-07-19 10:34:38 +0200358 } else if (rtp_video_sender_->IsActive() && !previously_active) {
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200359 // Payload router switched from inactive to active.
360 StartupVideoSendStream();
361 }
362}
363
364void VideoSendStreamImpl::Start() {
365 RTC_DCHECK_RUN_ON(worker_queue_);
366 RTC_LOG(LS_INFO) << "VideoSendStream::Start";
Stefan Holmer9416ef82018-07-19 10:34:38 +0200367 if (rtp_video_sender_->IsActive())
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200368 return;
369 TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Start");
Stefan Holmer9416ef82018-07-19 10:34:38 +0200370 rtp_video_sender_->SetActive(true);
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200371 StartupVideoSendStream();
372}
373
374void VideoSendStreamImpl::StartupVideoSendStream() {
375 RTC_DCHECK_RUN_ON(worker_queue_);
376 bitrate_allocator_->AddObserver(
Sebastian Jansson24ad7202018-04-19 08:25:12 +0200377 this,
378 MediaStreamAllocationConfig{
379 static_cast<uint32_t>(encoder_min_bitrate_bps_),
380 encoder_max_bitrate_bps_, static_cast<uint32_t>(max_padding_bitrate_),
381 !config_->suspend_below_min_bitrate, config_->track_id,
Sebastian Jansson79f0d4d2019-01-23 09:41:43 +0100382 encoder_bitrate_priority_});
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200383 // Start monitoring encoder activity.
384 {
Sebastian Janssonecb68972019-01-18 10:30:54 +0100385 RTC_DCHECK(!check_encoder_activity_task_.Running());
386
387 activity_ = false;
388 timed_out_ = false;
389 check_encoder_activity_task_ =
390 RepeatingTaskHandle::DelayedStart(kEncoderTimeOut, [this] {
391 RTC_DCHECK_RUN_ON(worker_queue_);
392 if (!activity_) {
393 if (!timed_out_) {
394 SignalEncoderTimedOut();
395 }
396 timed_out_ = true;
397 } else if (timed_out_) {
398 SignalEncoderActive();
399 timed_out_ = false;
400 }
401 activity_ = false;
402 return kEncoderTimeOut;
403 });
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200404 }
405
406 video_stream_encoder_->SendKeyFrame();
407}
408
409void VideoSendStreamImpl::Stop() {
410 RTC_DCHECK_RUN_ON(worker_queue_);
411 RTC_LOG(LS_INFO) << "VideoSendStream::Stop";
Stefan Holmer9416ef82018-07-19 10:34:38 +0200412 if (!rtp_video_sender_->IsActive())
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200413 return;
414 TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Stop");
Stefan Holmer9416ef82018-07-19 10:34:38 +0200415 rtp_video_sender_->SetActive(false);
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200416 StopVideoSendStream();
417}
418
419void VideoSendStreamImpl::StopVideoSendStream() {
420 bitrate_allocator_->RemoveObserver(this);
Sebastian Janssonecb68972019-01-18 10:30:54 +0100421 check_encoder_activity_task_.Stop();
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200422 video_stream_encoder_->OnBitrateUpdated(0, 0, 0);
423 stats_proxy_->OnSetEncoderTargetRate(0);
424}
425
426void VideoSendStreamImpl::SignalEncoderTimedOut() {
427 RTC_DCHECK_RUN_ON(worker_queue_);
Sebastian Janssonecb68972019-01-18 10:30:54 +0100428 // If the encoder has not produced anything the last kEncoderTimeOut and it
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200429 // is supposed to, deregister as BitrateAllocatorObserver. This can happen
430 // if a camera stops producing frames.
431 if (encoder_target_rate_bps_ > 0) {
432 RTC_LOG(LS_INFO) << "SignalEncoderTimedOut, Encoder timed out.";
433 bitrate_allocator_->RemoveObserver(this);
434 }
435}
436
437void VideoSendStreamImpl::OnBitrateAllocationUpdated(
Erik Språng566124a2018-04-23 12:32:22 +0200438 const VideoBitrateAllocation& allocation) {
Erik Språng4e193e42018-09-14 19:01:58 +0200439 if (!worker_queue_->IsCurrent()) {
440 auto ptr = weak_ptr_;
441 worker_queue_->PostTask([=] {
442 if (!ptr.get())
443 return;
444 ptr->OnBitrateAllocationUpdated(allocation);
445 });
446 return;
447 }
448
449 RTC_DCHECK_RUN_ON(worker_queue_);
450
451 int64_t now_ms = rtc::TimeMillis();
Erik Språngf4ef2dd2018-09-11 12:37:51 +0200452 if (encoder_target_rate_bps_ != 0) {
Erik Språng4e193e42018-09-14 19:01:58 +0200453 if (video_bitrate_allocation_context_) {
454 // If new allocation is within kMaxVbaSizeDifferencePercent larger than
455 // the previously sent allocation and the same streams are still enabled,
456 // it is considered "similar". We do not want send similar allocations
457 // more once per kMaxVbaThrottleTimeMs.
458 const VideoBitrateAllocation& last =
459 video_bitrate_allocation_context_->last_sent_allocation;
460 const bool is_similar =
461 allocation.get_sum_bps() >= last.get_sum_bps() &&
462 allocation.get_sum_bps() <
463 (last.get_sum_bps() * (100 + kMaxVbaSizeDifferencePercent)) /
464 100 &&
465 SameStreamsEnabled(allocation, last);
466 if (is_similar &&
467 (now_ms - video_bitrate_allocation_context_->last_send_time_ms) <
468 kMaxVbaThrottleTimeMs) {
469 // This allocation is too similar, cache it and return.
470 video_bitrate_allocation_context_->throttled_allocation = allocation;
471 return;
472 }
473 } else {
474 video_bitrate_allocation_context_.emplace();
475 }
476
477 video_bitrate_allocation_context_->last_sent_allocation = allocation;
478 video_bitrate_allocation_context_->throttled_allocation.reset();
479 video_bitrate_allocation_context_->last_send_time_ms = now_ms;
480
Erik Språngf4ef2dd2018-09-11 12:37:51 +0200481 // Send bitrate allocation metadata only if encoder is not paused.
482 rtp_video_sender_->OnBitrateAllocationUpdated(allocation);
483 }
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200484}
485
486void VideoSendStreamImpl::SignalEncoderActive() {
487 RTC_DCHECK_RUN_ON(worker_queue_);
488 RTC_LOG(LS_INFO) << "SignalEncoderActive, Encoder is active.";
489 bitrate_allocator_->AddObserver(
Sebastian Jansson24ad7202018-04-19 08:25:12 +0200490 this,
491 MediaStreamAllocationConfig{
492 static_cast<uint32_t>(encoder_min_bitrate_bps_),
493 encoder_max_bitrate_bps_, static_cast<uint32_t>(max_padding_bitrate_),
494 !config_->suspend_below_min_bitrate, config_->track_id,
Sebastian Jansson79f0d4d2019-01-23 09:41:43 +0100495 encoder_bitrate_priority_});
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200496}
497
498void VideoSendStreamImpl::OnEncoderConfigurationChanged(
499 std::vector<VideoStream> streams,
500 int min_transmit_bitrate_bps) {
501 if (!worker_queue_->IsCurrent()) {
502 rtc::WeakPtr<VideoSendStreamImpl> send_stream = weak_ptr_;
503 worker_queue_->PostTask([send_stream, streams, min_transmit_bitrate_bps]() {
504 if (send_stream)
505 send_stream->OnEncoderConfigurationChanged(std::move(streams),
506 min_transmit_bitrate_bps);
507 });
508 return;
509 }
510 RTC_DCHECK_GE(config_->rtp.ssrcs.size(), streams.size());
511 TRACE_EVENT0("webrtc", "VideoSendStream::OnEncoderConfigurationChanged");
512 RTC_DCHECK_GE(config_->rtp.ssrcs.size(), streams.size());
513 RTC_DCHECK_RUN_ON(worker_queue_);
514
515 encoder_min_bitrate_bps_ =
516 std::max(streams[0].min_bitrate_bps, GetEncoderMinBitrateBps());
517 encoder_max_bitrate_bps_ = 0;
518 double stream_bitrate_priority_sum = 0;
519 for (const auto& stream : streams) {
520 // We don't want to allocate more bitrate than needed to inactive streams.
521 encoder_max_bitrate_bps_ += stream.active ? stream.max_bitrate_bps : 0;
522 if (stream.bitrate_priority) {
523 RTC_DCHECK_GT(*stream.bitrate_priority, 0);
524 stream_bitrate_priority_sum += *stream.bitrate_priority;
525 }
526 }
527 RTC_DCHECK_GT(stream_bitrate_priority_sum, 0);
528 encoder_bitrate_priority_ = stream_bitrate_priority_sum;
529 encoder_max_bitrate_bps_ =
530 std::max(static_cast<uint32_t>(encoder_min_bitrate_bps_),
531 encoder_max_bitrate_bps_);
“Michael277a6562018-06-01 14:09:19 -0500532
533 const VideoCodecType codec_type =
534 PayloadStringToCodecType(config_->rtp.payload_name);
535 if (codec_type == kVideoCodecVP9) {
Sergey Silkin8b9b5f92018-12-10 09:28:53 +0100536 max_padding_bitrate_ = has_alr_probing_ ? streams[0].min_bitrate_bps
537 : streams[0].target_bitrate_bps;
“Michael277a6562018-06-01 14:09:19 -0500538 } else {
539 max_padding_bitrate_ = CalculateMaxPadBitrateBps(
Erik Språngb57ab382018-09-13 10:52:38 +0200540 streams, min_transmit_bitrate_bps, config_->suspend_below_min_bitrate,
541 has_alr_probing_);
“Michael277a6562018-06-01 14:09:19 -0500542 }
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200543
544 // Clear stats for disabled layers.
545 for (size_t i = streams.size(); i < config_->rtp.ssrcs.size(); ++i) {
546 stats_proxy_->OnInactiveSsrc(config_->rtp.ssrcs[i]);
547 }
548
549 const size_t num_temporal_layers =
550 streams.back().num_temporal_layers.value_or(1);
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200551
552 rtp_video_sender_->SetEncodingData(streams[0].width, streams[0].height,
553 num_temporal_layers);
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200554
Stefan Holmer9416ef82018-07-19 10:34:38 +0200555 if (rtp_video_sender_->IsActive()) {
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200556 // The send stream is started already. Update the allocator with new bitrate
557 // limits.
558 bitrate_allocator_->AddObserver(
Sebastian Jansson24ad7202018-04-19 08:25:12 +0200559 this, MediaStreamAllocationConfig{
560 static_cast<uint32_t>(encoder_min_bitrate_bps_),
561 encoder_max_bitrate_bps_,
562 static_cast<uint32_t>(max_padding_bitrate_),
563 !config_->suspend_below_min_bitrate, config_->track_id,
Sebastian Jansson79f0d4d2019-01-23 09:41:43 +0100564 encoder_bitrate_priority_});
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200565 }
566}
567
568EncodedImageCallback::Result VideoSendStreamImpl::OnEncodedImage(
569 const EncodedImage& encoded_image,
570 const CodecSpecificInfo* codec_specific_info,
571 const RTPFragmentationHeader* fragmentation) {
572 // Encoded is called on whatever thread the real encoder implementation run
573 // on. In the case of hardware encoders, there might be several encoders
574 // running in parallel on different threads.
Sebastian Janssonecb68972019-01-18 10:30:54 +0100575
576 // Indicate that there still is activity going on.
577 activity_ = true;
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200578
Niels Möller46879152019-01-07 15:54:47 +0100579 EncodedImageCallback::Result result(EncodedImageCallback::Result::OK);
580 if (media_transport_) {
581 int64_t frame_id;
582 {
583 // TODO(nisse): Responsibility for allocation of frame ids should move to
584 // VideoStreamEncoder.
585 rtc::CritScope cs(&media_transport_id_lock_);
586 frame_id = media_transport_frame_id_++;
587 }
588 // TODO(nisse): Responsibility for reference meta data should be moved
589 // upstream, ideally close to the encoders, but probably VideoStreamEncoder
590 // will need to do some translation to produce reference info using frame
591 // ids.
592 std::vector<int64_t> referenced_frame_ids;
593 if (encoded_image._frameType != kVideoFrameKey) {
594 RTC_DCHECK_GT(frame_id, 0);
595 referenced_frame_ids.push_back(frame_id - 1);
596 }
597 media_transport_->SendVideoFrame(
598 config_->rtp.ssrcs[0], webrtc::MediaTransportEncodedVideoFrame(
599 frame_id, referenced_frame_ids,
600 config_->rtp.payload_type, encoded_image));
601 } else {
602 result = rtp_video_sender_->OnEncodedImage(
603 encoded_image, codec_specific_info, fragmentation);
604 }
Erik Språng4e193e42018-09-14 19:01:58 +0200605 // Check if there's a throttled VideoBitrateAllocation that we should try
606 // sending.
607 rtc::WeakPtr<VideoSendStreamImpl> send_stream = weak_ptr_;
608 auto update_task = [send_stream]() {
609 if (send_stream) {
610 RTC_DCHECK_RUN_ON(send_stream->worker_queue_);
611 auto& context = send_stream->video_bitrate_allocation_context_;
612 if (context && context->throttled_allocation) {
613 send_stream->OnBitrateAllocationUpdated(*context->throttled_allocation);
614 }
615 }
616 };
617 if (!worker_queue_->IsCurrent()) {
618 worker_queue_->PostTask(update_task);
619 } else {
620 update_task();
621 }
622
623 return result;
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200624}
625
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200626std::map<uint32_t, RtpState> VideoSendStreamImpl::GetRtpStates() const {
Stefan Holmer9416ef82018-07-19 10:34:38 +0200627 return rtp_video_sender_->GetRtpStates();
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200628}
629
630std::map<uint32_t, RtpPayloadState> VideoSendStreamImpl::GetRtpPayloadStates()
631 const {
Stefan Holmer9416ef82018-07-19 10:34:38 +0200632 return rtp_video_sender_->GetRtpPayloadStates();
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200633}
634
Sebastian Janssonc0e4d452018-10-25 15:08:32 +0200635uint32_t VideoSendStreamImpl::OnBitrateUpdated(BitrateAllocationUpdate update) {
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200636 RTC_DCHECK_RUN_ON(worker_queue_);
Stefan Holmer9416ef82018-07-19 10:34:38 +0200637 RTC_DCHECK(rtp_video_sender_->IsActive())
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200638 << "VideoSendStream::Start has not been called.";
639
Sebastian Jansson13e59032018-11-21 19:13:07 +0100640 rtp_video_sender_->OnBitrateUpdated(
641 update.target_bitrate.bps(),
642 rtc::dchecked_cast<uint8_t>(update.packet_loss_ratio * 256),
643 update.round_trip_time.ms(), stats_proxy_->GetSendFrameRate());
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200644 encoder_target_rate_bps_ = rtp_video_sender_->GetPayloadBitrateBps();
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200645 encoder_target_rate_bps_ =
646 std::min(encoder_max_bitrate_bps_, encoder_target_rate_bps_);
Sebastian Jansson13e59032018-11-21 19:13:07 +0100647 video_stream_encoder_->OnBitrateUpdated(
648 encoder_target_rate_bps_,
649 rtc::dchecked_cast<uint8_t>(update.packet_loss_ratio * 256),
650 update.round_trip_time.ms());
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200651 stats_proxy_->OnSetEncoderTargetRate(encoder_target_rate_bps_);
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200652 return rtp_video_sender_->GetProtectionBitrateBps();
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200653}
654
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200655} // namespace internal
656} // namespace webrtc