blob: 13461c6783e99784c44e2b64290da3ed61ca6b73 [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 Holmerdbdb3a02018-07-17 16:03:46 +0200114// call_stats,
115// &encoder_feedback_,
116// stats_proxy_,
117// stats_proxy_,
118// stats_proxy_,
119// stats_proxy_,
120// stats_proxy_,
121// stats_proxy_,
122// send_delay_stats,
123// this
124RtpSenderObservers CreateObservers(CallStats* call_stats,
125 EncoderRtcpFeedback* encoder_feedback,
126 SendStatisticsProxy* stats_proxy,
127 SendDelayStats* send_delay_stats,
128 OverheadObserver* overhead_observer) {
129 RtpSenderObservers observers;
130 observers.rtcp_rtt_stats = call_stats;
131 observers.intra_frame_callback = encoder_feedback;
132 observers.rtcp_stats = stats_proxy;
133 observers.rtp_stats = stats_proxy;
134 observers.bitrate_observer = stats_proxy;
135 observers.frame_count_observer = stats_proxy;
136 observers.rtcp_type_observer = stats_proxy;
137 observers.send_delay_observer = stats_proxy;
138 observers.send_packet_observer = send_delay_stats;
139 observers.overhead_observer = overhead_observer;
140 return observers;
141}
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200142} // namespace
143
144// CheckEncoderActivityTask is used for tracking when the encoder last produced
145// and encoded video frame. If the encoder has not produced anything the last
146// kEncoderTimeOutMs we also want to stop sending padding.
147class VideoSendStreamImpl::CheckEncoderActivityTask : public rtc::QueuedTask {
148 public:
149 static const int kEncoderTimeOutMs = 2000;
150 explicit CheckEncoderActivityTask(
151 const rtc::WeakPtr<VideoSendStreamImpl>& send_stream)
152 : activity_(0), send_stream_(std::move(send_stream)), timed_out_(false) {}
153
154 void Stop() {
155 RTC_CHECK(task_checker_.CalledSequentially());
156 send_stream_.reset();
157 }
158
159 void UpdateEncoderActivity() {
160 // UpdateEncoderActivity is called from VideoSendStreamImpl::Encoded on
161 // whatever thread the real encoder implementation run on. In the case of
162 // hardware encoders, there might be several encoders
163 // running in parallel on different threads.
164 rtc::AtomicOps::ReleaseStore(&activity_, 1);
165 }
166
167 private:
168 bool Run() override {
169 RTC_CHECK(task_checker_.CalledSequentially());
170 if (!send_stream_)
171 return true;
172 if (!rtc::AtomicOps::AcquireLoad(&activity_)) {
173 if (!timed_out_) {
174 send_stream_->SignalEncoderTimedOut();
175 }
176 timed_out_ = true;
177 } else if (timed_out_) {
178 send_stream_->SignalEncoderActive();
179 timed_out_ = false;
180 }
181 rtc::AtomicOps::ReleaseStore(&activity_, 0);
182
183 rtc::TaskQueue::Current()->PostDelayedTask(
184 std::unique_ptr<rtc::QueuedTask>(this), kEncoderTimeOutMs);
185 // Return false to prevent this task from being deleted. Ownership has been
186 // transferred to the task queue when PostDelayedTask was called.
187 return false;
188 }
189 volatile int activity_;
190
191 rtc::SequencedTaskChecker task_checker_;
192 rtc::WeakPtr<VideoSendStreamImpl> send_stream_;
193 bool timed_out_;
194};
195
196VideoSendStreamImpl::VideoSendStreamImpl(
197 SendStatisticsProxy* stats_proxy,
198 rtc::TaskQueue* worker_queue,
199 CallStats* call_stats,
200 RtpTransportControllerSendInterface* transport,
Sebastian Jansson652dc912018-04-19 17:09:15 +0200201 BitrateAllocatorInterface* bitrate_allocator,
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200202 SendDelayStats* send_delay_stats,
Sebastian Jansson652dc912018-04-19 17:09:15 +0200203 VideoStreamEncoderInterface* video_stream_encoder,
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200204 RtcEventLog* event_log,
205 const VideoSendStream::Config* config,
206 int initial_encoder_max_bitrate,
207 double initial_encoder_bitrate_priority,
208 std::map<uint32_t, RtpState> suspended_ssrcs,
209 std::map<uint32_t, RtpPayloadState> suspended_payload_states,
210 VideoEncoderConfig::ContentType content_type,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200211 std::unique_ptr<FecController> fec_controller)
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200212 : send_side_bwe_with_overhead_(
213 webrtc::field_trial::IsEnabled("WebRTC-SendSideBwe-WithOverhead")),
214 stats_proxy_(stats_proxy),
215 config_(config),
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200216 fec_controller_(std::move(fec_controller)),
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200217 worker_queue_(worker_queue),
218 check_encoder_activity_task_(nullptr),
219 call_stats_(call_stats),
220 transport_(transport),
221 bitrate_allocator_(bitrate_allocator),
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200222 max_padding_bitrate_(0),
223 encoder_min_bitrate_bps_(0),
224 encoder_target_rate_bps_(0),
225 encoder_bitrate_priority_(initial_encoder_bitrate_priority),
226 has_packet_feedback_(false),
227 video_stream_encoder_(video_stream_encoder),
228 encoder_feedback_(Clock::GetRealTimeClock(),
229 config_->rtp.ssrcs,
230 video_stream_encoder),
231 bandwidth_observer_(transport->GetBandwidthObserver()),
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200232 payload_router_(
233 transport_->CreateVideoRtpSender(config_->rtp.ssrcs,
234 suspended_ssrcs,
235 suspended_payload_states,
236 config_->rtp,
237 config_->rtcp,
238 config_->send_transport,
239 CreateObservers(call_stats,
240 &encoder_feedback_,
241 stats_proxy_,
242 send_delay_stats,
243 this),
244 event_log)),
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200245 weak_ptr_factory_(this),
246 overhead_bytes_per_packet_(0),
247 transport_overhead_bytes_per_packet_(0) {
248 RTC_DCHECK_RUN_ON(worker_queue_);
249 RTC_LOG(LS_INFO) << "VideoSendStreamInternal: " << config_->ToString();
250 weak_ptr_ = weak_ptr_factory_.GetWeakPtr();
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200251
252 RTC_DCHECK(!config_->rtp.ssrcs.empty());
253 RTC_DCHECK(call_stats_);
254 RTC_DCHECK(transport_);
255 RTC_DCHECK_NE(initial_encoder_max_bitrate, 0);
256
257 if (initial_encoder_max_bitrate > 0) {
258 encoder_max_bitrate_bps_ =
259 rtc::dchecked_cast<uint32_t>(initial_encoder_max_bitrate);
260 } else {
261 // TODO(srte): Make sure max bitrate is not set to negative values. We don't
262 // have any way to handle unset values in downstream code, such as the
263 // bitrate allocator. Previously -1 was implicitly casted to UINT32_MAX, a
264 // behaviour that is not safe. Converting to 10 Mbps should be safe for
265 // reasonable use cases as it allows adding the max of multiple streams
266 // without wrappping around.
267 const int kFallbackMaxBitrateBps = 10000000;
268 RTC_DLOG(LS_ERROR) << "ERROR: Initial encoder max bitrate = "
269 << initial_encoder_max_bitrate << " which is <= 0!";
270 RTC_DLOG(LS_INFO) << "Using default encoder max bitrate = 10 Mbps";
271 encoder_max_bitrate_bps_ = kFallbackMaxBitrateBps;
272 }
273
274 RTC_CHECK(AlrExperimentSettings::MaxOneFieldTrialEnabled());
275 // If send-side BWE is enabled, check if we should apply updated probing and
276 // pacing settings.
277 if (TransportSeqNumExtensionConfigured(*config_)) {
278 has_packet_feedback_ = true;
279
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200280 absl::optional<AlrExperimentSettings> alr_settings;
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200281 if (content_type == VideoEncoderConfig::ContentType::kScreen) {
282 alr_settings = AlrExperimentSettings::CreateFromFieldTrial(
283 AlrExperimentSettings::kScreenshareProbingBweExperimentName);
284 } else {
285 alr_settings = AlrExperimentSettings::CreateFromFieldTrial(
286 AlrExperimentSettings::kStrictPacingAndProbingExperimentName);
287 }
288 if (alr_settings) {
289 transport->EnablePeriodicAlrProbing(true);
290 transport->SetPacingFactor(alr_settings->pacing_factor);
291 configured_pacing_factor_ = alr_settings->pacing_factor;
292 transport->SetQueueTimeLimit(alr_settings->max_paced_queue_time);
293 } else {
294 transport->EnablePeriodicAlrProbing(false);
295 transport->SetPacingFactor(PacedSender::kDefaultPaceMultiplier);
296 configured_pacing_factor_ = PacedSender::kDefaultPaceMultiplier;
297 transport->SetQueueTimeLimit(PacedSender::kMaxQueueLengthMs);
298 }
299 }
300
301 if (config_->periodic_alr_bandwidth_probing) {
302 transport->EnablePeriodicAlrProbing(true);
303 }
304
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200305 // Currently, both ULPFEC and FlexFEC use the same FEC rate calculation logic,
306 // so enable that logic if either of those FEC schemes are enabled.
307 fec_controller_->SetProtectionMethod(payload_router_->FecEnabled(),
308 payload_router_->NackEnabled());
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200309
310 fec_controller_->SetProtectionCallback(this);
311 // Signal congestion controller this object is ready for OnPacket* callbacks.
312 if (fec_controller_->UseLossVectorMask()) {
313 transport_->RegisterPacketFeedbackObserver(this);
314 }
315
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200316 RTC_DCHECK_GE(config_->rtp.payload_type, 0);
317 RTC_DCHECK_LE(config_->rtp.payload_type, 127);
318
319 video_stream_encoder_->SetStartBitrate(
320 bitrate_allocator_->GetStartBitrate(this));
321
322 // Only request rotation at the source when we positively know that the remote
323 // side doesn't support the rotation extension. This allows us to prepare the
324 // encoder in the expectation that rotation is supported - which is the common
325 // case.
326 bool rotation_applied =
327 std::find_if(config_->rtp.extensions.begin(),
328 config_->rtp.extensions.end(),
329 [](const RtpExtension& extension) {
330 return extension.uri == RtpExtension::kVideoRotationUri;
331 }) == config_->rtp.extensions.end();
332
333 video_stream_encoder_->SetSink(this, rotation_applied);
334}
335
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200336VideoSendStreamImpl::~VideoSendStreamImpl() {
337 RTC_DCHECK_RUN_ON(worker_queue_);
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200338 RTC_DCHECK(!payload_router_->IsActive())
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200339 << "VideoSendStreamImpl::Stop not called";
340 RTC_LOG(LS_INFO) << "~VideoSendStreamInternal: " << config_->ToString();
341 if (fec_controller_->UseLossVectorMask()) {
342 transport_->DeRegisterPacketFeedbackObserver(this);
343 }
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200344}
345
346void VideoSendStreamImpl::RegisterProcessThread(
347 ProcessThread* module_process_thread) {
348 payload_router_->RegisterProcessThread(module_process_thread);
349}
350
351void VideoSendStreamImpl::DeRegisterProcessThread() {
352 payload_router_->DeRegisterProcessThread();
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200353}
354
355bool VideoSendStreamImpl::DeliverRtcp(const uint8_t* packet, size_t length) {
356 // Runs on a network thread.
357 RTC_DCHECK(!worker_queue_->IsCurrent());
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200358 payload_router_->DeliverRtcp(packet, length);
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200359 return true;
360}
361
362void VideoSendStreamImpl::UpdateActiveSimulcastLayers(
363 const std::vector<bool> active_layers) {
364 RTC_DCHECK_RUN_ON(worker_queue_);
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200365 RTC_LOG(LS_INFO) << "VideoSendStream::UpdateActiveSimulcastLayers";
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200366 bool previously_active = payload_router_->IsActive();
367 payload_router_->SetActiveModules(active_layers);
368 if (!payload_router_->IsActive() && previously_active) {
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200369 // Payload router switched from active to inactive.
370 StopVideoSendStream();
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200371 } else if (payload_router_->IsActive() && !previously_active) {
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200372 // Payload router switched from inactive to active.
373 StartupVideoSendStream();
374 }
375}
376
377void VideoSendStreamImpl::Start() {
378 RTC_DCHECK_RUN_ON(worker_queue_);
379 RTC_LOG(LS_INFO) << "VideoSendStream::Start";
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200380 if (payload_router_->IsActive())
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200381 return;
382 TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Start");
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200383 payload_router_->SetActive(true);
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200384 StartupVideoSendStream();
385}
386
387void VideoSendStreamImpl::StartupVideoSendStream() {
388 RTC_DCHECK_RUN_ON(worker_queue_);
389 bitrate_allocator_->AddObserver(
Sebastian Jansson24ad7202018-04-19 08:25:12 +0200390 this,
391 MediaStreamAllocationConfig{
392 static_cast<uint32_t>(encoder_min_bitrate_bps_),
393 encoder_max_bitrate_bps_, static_cast<uint32_t>(max_padding_bitrate_),
394 !config_->suspend_below_min_bitrate, config_->track_id,
395 encoder_bitrate_priority_, has_packet_feedback_});
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200396 // Start monitoring encoder activity.
397 {
398 rtc::CritScope lock(&encoder_activity_crit_sect_);
399 RTC_DCHECK(!check_encoder_activity_task_);
400 check_encoder_activity_task_ = new CheckEncoderActivityTask(weak_ptr_);
401 worker_queue_->PostDelayedTask(
402 std::unique_ptr<rtc::QueuedTask>(check_encoder_activity_task_),
403 CheckEncoderActivityTask::kEncoderTimeOutMs);
404 }
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 Holmerdbdb3a02018-07-17 16:03:46 +0200412 if (!payload_router_->IsActive())
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200413 return;
414 TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Stop");
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200415 payload_router_->SetActive(false);
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200416 StopVideoSendStream();
417}
418
419void VideoSendStreamImpl::StopVideoSendStream() {
420 bitrate_allocator_->RemoveObserver(this);
421 {
422 rtc::CritScope lock(&encoder_activity_crit_sect_);
423 check_encoder_activity_task_->Stop();
424 check_encoder_activity_task_ = nullptr;
425 }
426 video_stream_encoder_->OnBitrateUpdated(0, 0, 0);
427 stats_proxy_->OnSetEncoderTargetRate(0);
428}
429
430void VideoSendStreamImpl::SignalEncoderTimedOut() {
431 RTC_DCHECK_RUN_ON(worker_queue_);
432 // If the encoder has not produced anything the last kEncoderTimeOutMs and it
433 // is supposed to, deregister as BitrateAllocatorObserver. This can happen
434 // if a camera stops producing frames.
435 if (encoder_target_rate_bps_ > 0) {
436 RTC_LOG(LS_INFO) << "SignalEncoderTimedOut, Encoder timed out.";
437 bitrate_allocator_->RemoveObserver(this);
438 }
439}
440
441void VideoSendStreamImpl::OnBitrateAllocationUpdated(
Erik Språng566124a2018-04-23 12:32:22 +0200442 const VideoBitrateAllocation& allocation) {
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200443 payload_router_->OnBitrateAllocationUpdated(allocation);
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200444}
445
446void VideoSendStreamImpl::SignalEncoderActive() {
447 RTC_DCHECK_RUN_ON(worker_queue_);
448 RTC_LOG(LS_INFO) << "SignalEncoderActive, Encoder is active.";
449 bitrate_allocator_->AddObserver(
Sebastian Jansson24ad7202018-04-19 08:25:12 +0200450 this,
451 MediaStreamAllocationConfig{
452 static_cast<uint32_t>(encoder_min_bitrate_bps_),
453 encoder_max_bitrate_bps_, static_cast<uint32_t>(max_padding_bitrate_),
454 !config_->suspend_below_min_bitrate, config_->track_id,
455 encoder_bitrate_priority_, has_packet_feedback_});
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200456}
457
458void VideoSendStreamImpl::OnEncoderConfigurationChanged(
459 std::vector<VideoStream> streams,
460 int min_transmit_bitrate_bps) {
461 if (!worker_queue_->IsCurrent()) {
462 rtc::WeakPtr<VideoSendStreamImpl> send_stream = weak_ptr_;
463 worker_queue_->PostTask([send_stream, streams, min_transmit_bitrate_bps]() {
464 if (send_stream)
465 send_stream->OnEncoderConfigurationChanged(std::move(streams),
466 min_transmit_bitrate_bps);
467 });
468 return;
469 }
470 RTC_DCHECK_GE(config_->rtp.ssrcs.size(), streams.size());
471 TRACE_EVENT0("webrtc", "VideoSendStream::OnEncoderConfigurationChanged");
472 RTC_DCHECK_GE(config_->rtp.ssrcs.size(), streams.size());
473 RTC_DCHECK_RUN_ON(worker_queue_);
474
475 encoder_min_bitrate_bps_ =
476 std::max(streams[0].min_bitrate_bps, GetEncoderMinBitrateBps());
477 encoder_max_bitrate_bps_ = 0;
478 double stream_bitrate_priority_sum = 0;
479 for (const auto& stream : streams) {
480 // We don't want to allocate more bitrate than needed to inactive streams.
481 encoder_max_bitrate_bps_ += stream.active ? stream.max_bitrate_bps : 0;
482 if (stream.bitrate_priority) {
483 RTC_DCHECK_GT(*stream.bitrate_priority, 0);
484 stream_bitrate_priority_sum += *stream.bitrate_priority;
485 }
486 }
487 RTC_DCHECK_GT(stream_bitrate_priority_sum, 0);
488 encoder_bitrate_priority_ = stream_bitrate_priority_sum;
489 encoder_max_bitrate_bps_ =
490 std::max(static_cast<uint32_t>(encoder_min_bitrate_bps_),
491 encoder_max_bitrate_bps_);
“Michael277a6562018-06-01 14:09:19 -0500492
493 const VideoCodecType codec_type =
494 PayloadStringToCodecType(config_->rtp.payload_name);
495 if (codec_type == kVideoCodecVP9) {
496 max_padding_bitrate_ = streams[0].target_bitrate_bps;
497 } else {
498 max_padding_bitrate_ = CalculateMaxPadBitrateBps(
499 streams, min_transmit_bitrate_bps, config_->suspend_below_min_bitrate);
500 }
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200501
502 // Clear stats for disabled layers.
503 for (size_t i = streams.size(); i < config_->rtp.ssrcs.size(); ++i) {
504 stats_proxy_->OnInactiveSsrc(config_->rtp.ssrcs[i]);
505 }
506
507 const size_t num_temporal_layers =
508 streams.back().num_temporal_layers.value_or(1);
509 fec_controller_->SetEncodingData(streams[0].width, streams[0].height,
510 num_temporal_layers,
511 config_->rtp.max_packet_size);
512
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200513 if (payload_router_->IsActive()) {
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200514 // The send stream is started already. Update the allocator with new bitrate
515 // limits.
516 bitrate_allocator_->AddObserver(
Sebastian Jansson24ad7202018-04-19 08:25:12 +0200517 this, MediaStreamAllocationConfig{
518 static_cast<uint32_t>(encoder_min_bitrate_bps_),
519 encoder_max_bitrate_bps_,
520 static_cast<uint32_t>(max_padding_bitrate_),
521 !config_->suspend_below_min_bitrate, config_->track_id,
522 encoder_bitrate_priority_, has_packet_feedback_});
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200523 }
524}
525
526EncodedImageCallback::Result VideoSendStreamImpl::OnEncodedImage(
527 const EncodedImage& encoded_image,
528 const CodecSpecificInfo* codec_specific_info,
529 const RTPFragmentationHeader* fragmentation) {
530 // Encoded is called on whatever thread the real encoder implementation run
531 // on. In the case of hardware encoders, there might be several encoders
532 // running in parallel on different threads.
533 size_t simulcast_idx = 0;
534 if (codec_specific_info->codecType == kVideoCodecVP8) {
535 simulcast_idx = codec_specific_info->codecSpecific.VP8.simulcastIdx;
536 }
537 if (config_->post_encode_callback) {
538 config_->post_encode_callback->EncodedFrameCallback(EncodedFrame(
539 encoded_image._buffer, encoded_image._length, encoded_image._frameType,
540 simulcast_idx, encoded_image._timeStamp));
541 }
542 {
543 rtc::CritScope lock(&encoder_activity_crit_sect_);
544 if (check_encoder_activity_task_)
545 check_encoder_activity_task_->UpdateEncoderActivity();
546 }
547
548 fec_controller_->UpdateWithEncodedData(encoded_image._length,
549 encoded_image._frameType);
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200550 EncodedImageCallback::Result result = payload_router_->OnEncodedImage(
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200551 encoded_image, codec_specific_info, fragmentation);
552
553 RTC_DCHECK(codec_specific_info);
554
555 int layer = codec_specific_info->codecType == kVideoCodecVP8
556 ? codec_specific_info->codecSpecific.VP8.simulcastIdx
557 : 0;
558 {
559 rtc::CritScope lock(&ivf_writers_crit_);
560 if (file_writers_[layer].get()) {
561 bool ok = file_writers_[layer]->WriteFrame(
562 encoded_image, codec_specific_info->codecType);
563 RTC_DCHECK(ok);
564 }
565 }
566
567 return result;
568}
569
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200570std::map<uint32_t, RtpState> VideoSendStreamImpl::GetRtpStates() const {
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200571 return payload_router_->GetRtpStates();
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200572}
573
574std::map<uint32_t, RtpPayloadState> VideoSendStreamImpl::GetRtpPayloadStates()
575 const {
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200576 return payload_router_->GetRtpPayloadStates();
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200577}
578
579uint32_t VideoSendStreamImpl::OnBitrateUpdated(uint32_t bitrate_bps,
580 uint8_t fraction_loss,
581 int64_t rtt,
582 int64_t probing_interval_ms) {
583 RTC_DCHECK_RUN_ON(worker_queue_);
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200584 RTC_DCHECK(payload_router_->IsActive())
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200585 << "VideoSendStream::Start has not been called.";
586
587 // Substract overhead from bitrate.
588 rtc::CritScope lock(&overhead_bytes_per_packet_crit_);
589 uint32_t payload_bitrate_bps = bitrate_bps;
590 if (send_side_bwe_with_overhead_) {
591 payload_bitrate_bps -= CalculateOverheadRateBps(
592 CalculatePacketRate(bitrate_bps,
593 config_->rtp.max_packet_size +
594 transport_overhead_bytes_per_packet_),
595 overhead_bytes_per_packet_ + transport_overhead_bytes_per_packet_,
596 bitrate_bps);
597 }
598
599 // Get the encoder target rate. It is the estimated network rate -
600 // protection overhead.
601 encoder_target_rate_bps_ = fec_controller_->UpdateFecRates(
602 payload_bitrate_bps, stats_proxy_->GetSendFrameRate(), fraction_loss,
603 loss_mask_vector_, rtt);
604 loss_mask_vector_.clear();
605
606 uint32_t encoder_overhead_rate_bps =
607 send_side_bwe_with_overhead_
608 ? CalculateOverheadRateBps(
609 CalculatePacketRate(encoder_target_rate_bps_,
610 config_->rtp.max_packet_size +
611 transport_overhead_bytes_per_packet_ -
612 overhead_bytes_per_packet_),
613 overhead_bytes_per_packet_ +
614 transport_overhead_bytes_per_packet_,
615 bitrate_bps - encoder_target_rate_bps_)
616 : 0;
617
618 // When the field trial "WebRTC-SendSideBwe-WithOverhead" is enabled
619 // protection_bitrate includes overhead.
620 uint32_t protection_bitrate =
621 bitrate_bps - (encoder_target_rate_bps_ + encoder_overhead_rate_bps);
622
623 encoder_target_rate_bps_ =
624 std::min(encoder_max_bitrate_bps_, encoder_target_rate_bps_);
625 video_stream_encoder_->OnBitrateUpdated(encoder_target_rate_bps_,
626 fraction_loss, rtt);
627 stats_proxy_->OnSetEncoderTargetRate(encoder_target_rate_bps_);
628 return protection_bitrate;
629}
630
631void VideoSendStreamImpl::EnableEncodedFrameRecording(
632 const std::vector<rtc::PlatformFile>& files,
633 size_t byte_limit) {
634 {
635 rtc::CritScope lock(&ivf_writers_crit_);
636 for (unsigned int i = 0; i < kMaxSimulcastStreams; ++i) {
637 if (i < files.size()) {
638 file_writers_[i] = IvfFileWriter::Wrap(rtc::File(files[i]), byte_limit);
639 } else {
640 file_writers_[i].reset();
641 }
642 }
643 }
644
645 if (!files.empty()) {
646 // Make a keyframe appear as early as possible in the logs, to give actually
647 // decodable output.
648 video_stream_encoder_->SendKeyFrame();
649 }
650}
651
652int VideoSendStreamImpl::ProtectionRequest(
653 const FecProtectionParams* delta_params,
654 const FecProtectionParams* key_params,
655 uint32_t* sent_video_rate_bps,
656 uint32_t* sent_nack_rate_bps,
657 uint32_t* sent_fec_rate_bps) {
658 RTC_DCHECK_RUN_ON(worker_queue_);
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200659 payload_router_->ProtectionRequest(delta_params, key_params,
660 sent_video_rate_bps, sent_nack_rate_bps,
661 sent_fec_rate_bps);
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200662 return 0;
663}
664
665void VideoSendStreamImpl::OnOverheadChanged(size_t overhead_bytes_per_packet) {
666 rtc::CritScope lock(&overhead_bytes_per_packet_crit_);
667 overhead_bytes_per_packet_ = overhead_bytes_per_packet;
668}
669
670void VideoSendStreamImpl::SetTransportOverhead(
671 size_t transport_overhead_bytes_per_packet) {
672 if (transport_overhead_bytes_per_packet >= static_cast<int>(kPathMTU)) {
673 RTC_LOG(LS_ERROR) << "Transport overhead exceeds size of ethernet frame";
674 return;
675 }
676
677 transport_overhead_bytes_per_packet_ = transport_overhead_bytes_per_packet;
678
679 size_t rtp_packet_size =
680 std::min(config_->rtp.max_packet_size,
681 kPathMTU - transport_overhead_bytes_per_packet_);
682
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200683 payload_router_->SetMaxRtpPacketSize(rtp_packet_size);
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200684}
685
686void VideoSendStreamImpl::OnPacketAdded(uint32_t ssrc, uint16_t seq_num) {
687 if (!worker_queue_->IsCurrent()) {
688 auto ptr = weak_ptr_;
689 worker_queue_->PostTask([=] {
690 if (!ptr.get())
691 return;
692 ptr->OnPacketAdded(ssrc, seq_num);
693 });
694 return;
695 }
696 const auto ssrcs = config_->rtp.ssrcs;
697 if (std::find(ssrcs.begin(), ssrcs.end(), ssrc) != ssrcs.end()) {
698 feedback_packet_seq_num_set_.insert(seq_num);
699 if (feedback_packet_seq_num_set_.size() > kSendSideSeqNumSetMaxSize) {
700 RTC_LOG(LS_WARNING) << "Feedback packet sequence number set exceed it's "
701 "max size', will get reset.";
702 feedback_packet_seq_num_set_.clear();
703 }
704 }
705}
706
707void VideoSendStreamImpl::OnPacketFeedbackVector(
708 const std::vector<PacketFeedback>& packet_feedback_vector) {
709 if (!worker_queue_->IsCurrent()) {
710 auto ptr = weak_ptr_;
711 worker_queue_->PostTask([=] {
712 if (!ptr.get())
713 return;
714 ptr->OnPacketFeedbackVector(packet_feedback_vector);
715 });
716 return;
717 }
718 // Lost feedbacks are not considered to be lost packets.
719 for (const PacketFeedback& packet : packet_feedback_vector) {
720 if (auto it = feedback_packet_seq_num_set_.find(packet.sequence_number) !=
721 feedback_packet_seq_num_set_.end()) {
722 const bool lost = packet.arrival_time_ms == PacketFeedback::kNotReceived;
723 loss_mask_vector_.push_back(lost);
724 feedback_packet_seq_num_set_.erase(it);
725 }
726 }
727}
728} // namespace internal
729} // namespace webrtc