blob: 303dc5489f9d99ed7d80820f7a69cab3782b16e2 [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 Holmer5ed25af2018-07-18 15:17:14 +0200344 transport_->DestroyVideoRtpSender(payload_router_);
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200345}
346
347void VideoSendStreamImpl::RegisterProcessThread(
348 ProcessThread* module_process_thread) {
349 payload_router_->RegisterProcessThread(module_process_thread);
350}
351
352void VideoSendStreamImpl::DeRegisterProcessThread() {
353 payload_router_->DeRegisterProcessThread();
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200354}
355
356bool VideoSendStreamImpl::DeliverRtcp(const uint8_t* packet, size_t length) {
357 // Runs on a network thread.
358 RTC_DCHECK(!worker_queue_->IsCurrent());
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200359 payload_router_->DeliverRtcp(packet, length);
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200360 return true;
361}
362
363void VideoSendStreamImpl::UpdateActiveSimulcastLayers(
364 const std::vector<bool> active_layers) {
365 RTC_DCHECK_RUN_ON(worker_queue_);
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200366 RTC_LOG(LS_INFO) << "VideoSendStream::UpdateActiveSimulcastLayers";
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200367 bool previously_active = payload_router_->IsActive();
368 payload_router_->SetActiveModules(active_layers);
369 if (!payload_router_->IsActive() && previously_active) {
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200370 // Payload router switched from active to inactive.
371 StopVideoSendStream();
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200372 } else if (payload_router_->IsActive() && !previously_active) {
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200373 // Payload router switched from inactive to active.
374 StartupVideoSendStream();
375 }
376}
377
378void VideoSendStreamImpl::Start() {
379 RTC_DCHECK_RUN_ON(worker_queue_);
380 RTC_LOG(LS_INFO) << "VideoSendStream::Start";
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200381 if (payload_router_->IsActive())
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200382 return;
383 TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Start");
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200384 payload_router_->SetActive(true);
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200385 StartupVideoSendStream();
386}
387
388void VideoSendStreamImpl::StartupVideoSendStream() {
389 RTC_DCHECK_RUN_ON(worker_queue_);
390 bitrate_allocator_->AddObserver(
Sebastian Jansson24ad7202018-04-19 08:25:12 +0200391 this,
392 MediaStreamAllocationConfig{
393 static_cast<uint32_t>(encoder_min_bitrate_bps_),
394 encoder_max_bitrate_bps_, static_cast<uint32_t>(max_padding_bitrate_),
395 !config_->suspend_below_min_bitrate, config_->track_id,
396 encoder_bitrate_priority_, has_packet_feedback_});
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200397 // Start monitoring encoder activity.
398 {
399 rtc::CritScope lock(&encoder_activity_crit_sect_);
400 RTC_DCHECK(!check_encoder_activity_task_);
401 check_encoder_activity_task_ = new CheckEncoderActivityTask(weak_ptr_);
402 worker_queue_->PostDelayedTask(
403 std::unique_ptr<rtc::QueuedTask>(check_encoder_activity_task_),
404 CheckEncoderActivityTask::kEncoderTimeOutMs);
405 }
406
407 video_stream_encoder_->SendKeyFrame();
408}
409
410void VideoSendStreamImpl::Stop() {
411 RTC_DCHECK_RUN_ON(worker_queue_);
412 RTC_LOG(LS_INFO) << "VideoSendStream::Stop";
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200413 if (!payload_router_->IsActive())
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200414 return;
415 TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Stop");
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200416 payload_router_->SetActive(false);
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200417 StopVideoSendStream();
418}
419
420void VideoSendStreamImpl::StopVideoSendStream() {
421 bitrate_allocator_->RemoveObserver(this);
422 {
423 rtc::CritScope lock(&encoder_activity_crit_sect_);
424 check_encoder_activity_task_->Stop();
425 check_encoder_activity_task_ = nullptr;
426 }
427 video_stream_encoder_->OnBitrateUpdated(0, 0, 0);
428 stats_proxy_->OnSetEncoderTargetRate(0);
429}
430
431void VideoSendStreamImpl::SignalEncoderTimedOut() {
432 RTC_DCHECK_RUN_ON(worker_queue_);
433 // If the encoder has not produced anything the last kEncoderTimeOutMs and it
434 // is supposed to, deregister as BitrateAllocatorObserver. This can happen
435 // if a camera stops producing frames.
436 if (encoder_target_rate_bps_ > 0) {
437 RTC_LOG(LS_INFO) << "SignalEncoderTimedOut, Encoder timed out.";
438 bitrate_allocator_->RemoveObserver(this);
439 }
440}
441
442void VideoSendStreamImpl::OnBitrateAllocationUpdated(
Erik Språng566124a2018-04-23 12:32:22 +0200443 const VideoBitrateAllocation& allocation) {
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200444 payload_router_->OnBitrateAllocationUpdated(allocation);
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200445}
446
447void VideoSendStreamImpl::SignalEncoderActive() {
448 RTC_DCHECK_RUN_ON(worker_queue_);
449 RTC_LOG(LS_INFO) << "SignalEncoderActive, Encoder is active.";
450 bitrate_allocator_->AddObserver(
Sebastian Jansson24ad7202018-04-19 08:25:12 +0200451 this,
452 MediaStreamAllocationConfig{
453 static_cast<uint32_t>(encoder_min_bitrate_bps_),
454 encoder_max_bitrate_bps_, static_cast<uint32_t>(max_padding_bitrate_),
455 !config_->suspend_below_min_bitrate, config_->track_id,
456 encoder_bitrate_priority_, has_packet_feedback_});
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200457}
458
459void VideoSendStreamImpl::OnEncoderConfigurationChanged(
460 std::vector<VideoStream> streams,
461 int min_transmit_bitrate_bps) {
462 if (!worker_queue_->IsCurrent()) {
463 rtc::WeakPtr<VideoSendStreamImpl> send_stream = weak_ptr_;
464 worker_queue_->PostTask([send_stream, streams, min_transmit_bitrate_bps]() {
465 if (send_stream)
466 send_stream->OnEncoderConfigurationChanged(std::move(streams),
467 min_transmit_bitrate_bps);
468 });
469 return;
470 }
471 RTC_DCHECK_GE(config_->rtp.ssrcs.size(), streams.size());
472 TRACE_EVENT0("webrtc", "VideoSendStream::OnEncoderConfigurationChanged");
473 RTC_DCHECK_GE(config_->rtp.ssrcs.size(), streams.size());
474 RTC_DCHECK_RUN_ON(worker_queue_);
475
476 encoder_min_bitrate_bps_ =
477 std::max(streams[0].min_bitrate_bps, GetEncoderMinBitrateBps());
478 encoder_max_bitrate_bps_ = 0;
479 double stream_bitrate_priority_sum = 0;
480 for (const auto& stream : streams) {
481 // We don't want to allocate more bitrate than needed to inactive streams.
482 encoder_max_bitrate_bps_ += stream.active ? stream.max_bitrate_bps : 0;
483 if (stream.bitrate_priority) {
484 RTC_DCHECK_GT(*stream.bitrate_priority, 0);
485 stream_bitrate_priority_sum += *stream.bitrate_priority;
486 }
487 }
488 RTC_DCHECK_GT(stream_bitrate_priority_sum, 0);
489 encoder_bitrate_priority_ = stream_bitrate_priority_sum;
490 encoder_max_bitrate_bps_ =
491 std::max(static_cast<uint32_t>(encoder_min_bitrate_bps_),
492 encoder_max_bitrate_bps_);
“Michael277a6562018-06-01 14:09:19 -0500493
494 const VideoCodecType codec_type =
495 PayloadStringToCodecType(config_->rtp.payload_name);
496 if (codec_type == kVideoCodecVP9) {
497 max_padding_bitrate_ = streams[0].target_bitrate_bps;
498 } else {
499 max_padding_bitrate_ = CalculateMaxPadBitrateBps(
500 streams, min_transmit_bitrate_bps, config_->suspend_below_min_bitrate);
501 }
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200502
503 // Clear stats for disabled layers.
504 for (size_t i = streams.size(); i < config_->rtp.ssrcs.size(); ++i) {
505 stats_proxy_->OnInactiveSsrc(config_->rtp.ssrcs[i]);
506 }
507
508 const size_t num_temporal_layers =
509 streams.back().num_temporal_layers.value_or(1);
510 fec_controller_->SetEncodingData(streams[0].width, streams[0].height,
511 num_temporal_layers,
512 config_->rtp.max_packet_size);
513
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200514 if (payload_router_->IsActive()) {
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200515 // The send stream is started already. Update the allocator with new bitrate
516 // limits.
517 bitrate_allocator_->AddObserver(
Sebastian Jansson24ad7202018-04-19 08:25:12 +0200518 this, MediaStreamAllocationConfig{
519 static_cast<uint32_t>(encoder_min_bitrate_bps_),
520 encoder_max_bitrate_bps_,
521 static_cast<uint32_t>(max_padding_bitrate_),
522 !config_->suspend_below_min_bitrate, config_->track_id,
523 encoder_bitrate_priority_, has_packet_feedback_});
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200524 }
525}
526
527EncodedImageCallback::Result VideoSendStreamImpl::OnEncodedImage(
528 const EncodedImage& encoded_image,
529 const CodecSpecificInfo* codec_specific_info,
530 const RTPFragmentationHeader* fragmentation) {
531 // Encoded is called on whatever thread the real encoder implementation run
532 // on. In the case of hardware encoders, there might be several encoders
533 // running in parallel on different threads.
534 size_t simulcast_idx = 0;
535 if (codec_specific_info->codecType == kVideoCodecVP8) {
536 simulcast_idx = codec_specific_info->codecSpecific.VP8.simulcastIdx;
537 }
538 if (config_->post_encode_callback) {
539 config_->post_encode_callback->EncodedFrameCallback(EncodedFrame(
540 encoded_image._buffer, encoded_image._length, encoded_image._frameType,
541 simulcast_idx, encoded_image._timeStamp));
542 }
543 {
544 rtc::CritScope lock(&encoder_activity_crit_sect_);
545 if (check_encoder_activity_task_)
546 check_encoder_activity_task_->UpdateEncoderActivity();
547 }
548
549 fec_controller_->UpdateWithEncodedData(encoded_image._length,
550 encoded_image._frameType);
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200551 EncodedImageCallback::Result result = payload_router_->OnEncodedImage(
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200552 encoded_image, codec_specific_info, fragmentation);
553
554 RTC_DCHECK(codec_specific_info);
555
556 int layer = codec_specific_info->codecType == kVideoCodecVP8
557 ? codec_specific_info->codecSpecific.VP8.simulcastIdx
558 : 0;
559 {
560 rtc::CritScope lock(&ivf_writers_crit_);
561 if (file_writers_[layer].get()) {
562 bool ok = file_writers_[layer]->WriteFrame(
563 encoded_image, codec_specific_info->codecType);
564 RTC_DCHECK(ok);
565 }
566 }
567
568 return result;
569}
570
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200571std::map<uint32_t, RtpState> VideoSendStreamImpl::GetRtpStates() const {
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200572 return payload_router_->GetRtpStates();
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200573}
574
575std::map<uint32_t, RtpPayloadState> VideoSendStreamImpl::GetRtpPayloadStates()
576 const {
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200577 return payload_router_->GetRtpPayloadStates();
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200578}
579
580uint32_t VideoSendStreamImpl::OnBitrateUpdated(uint32_t bitrate_bps,
581 uint8_t fraction_loss,
582 int64_t rtt,
583 int64_t probing_interval_ms) {
584 RTC_DCHECK_RUN_ON(worker_queue_);
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200585 RTC_DCHECK(payload_router_->IsActive())
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200586 << "VideoSendStream::Start has not been called.";
587
588 // Substract overhead from bitrate.
589 rtc::CritScope lock(&overhead_bytes_per_packet_crit_);
590 uint32_t payload_bitrate_bps = bitrate_bps;
591 if (send_side_bwe_with_overhead_) {
592 payload_bitrate_bps -= CalculateOverheadRateBps(
593 CalculatePacketRate(bitrate_bps,
594 config_->rtp.max_packet_size +
595 transport_overhead_bytes_per_packet_),
596 overhead_bytes_per_packet_ + transport_overhead_bytes_per_packet_,
597 bitrate_bps);
598 }
599
600 // Get the encoder target rate. It is the estimated network rate -
601 // protection overhead.
602 encoder_target_rate_bps_ = fec_controller_->UpdateFecRates(
603 payload_bitrate_bps, stats_proxy_->GetSendFrameRate(), fraction_loss,
604 loss_mask_vector_, rtt);
605 loss_mask_vector_.clear();
606
607 uint32_t encoder_overhead_rate_bps =
608 send_side_bwe_with_overhead_
609 ? CalculateOverheadRateBps(
610 CalculatePacketRate(encoder_target_rate_bps_,
611 config_->rtp.max_packet_size +
612 transport_overhead_bytes_per_packet_ -
613 overhead_bytes_per_packet_),
614 overhead_bytes_per_packet_ +
615 transport_overhead_bytes_per_packet_,
616 bitrate_bps - encoder_target_rate_bps_)
617 : 0;
618
619 // When the field trial "WebRTC-SendSideBwe-WithOverhead" is enabled
620 // protection_bitrate includes overhead.
621 uint32_t protection_bitrate =
622 bitrate_bps - (encoder_target_rate_bps_ + encoder_overhead_rate_bps);
623
624 encoder_target_rate_bps_ =
625 std::min(encoder_max_bitrate_bps_, encoder_target_rate_bps_);
626 video_stream_encoder_->OnBitrateUpdated(encoder_target_rate_bps_,
627 fraction_loss, rtt);
628 stats_proxy_->OnSetEncoderTargetRate(encoder_target_rate_bps_);
629 return protection_bitrate;
630}
631
632void VideoSendStreamImpl::EnableEncodedFrameRecording(
633 const std::vector<rtc::PlatformFile>& files,
634 size_t byte_limit) {
635 {
636 rtc::CritScope lock(&ivf_writers_crit_);
637 for (unsigned int i = 0; i < kMaxSimulcastStreams; ++i) {
638 if (i < files.size()) {
639 file_writers_[i] = IvfFileWriter::Wrap(rtc::File(files[i]), byte_limit);
640 } else {
641 file_writers_[i].reset();
642 }
643 }
644 }
645
646 if (!files.empty()) {
647 // Make a keyframe appear as early as possible in the logs, to give actually
648 // decodable output.
649 video_stream_encoder_->SendKeyFrame();
650 }
651}
652
653int VideoSendStreamImpl::ProtectionRequest(
654 const FecProtectionParams* delta_params,
655 const FecProtectionParams* key_params,
656 uint32_t* sent_video_rate_bps,
657 uint32_t* sent_nack_rate_bps,
658 uint32_t* sent_fec_rate_bps) {
659 RTC_DCHECK_RUN_ON(worker_queue_);
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200660 payload_router_->ProtectionRequest(delta_params, key_params,
661 sent_video_rate_bps, sent_nack_rate_bps,
662 sent_fec_rate_bps);
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200663 return 0;
664}
665
666void VideoSendStreamImpl::OnOverheadChanged(size_t overhead_bytes_per_packet) {
667 rtc::CritScope lock(&overhead_bytes_per_packet_crit_);
668 overhead_bytes_per_packet_ = overhead_bytes_per_packet;
669}
670
671void VideoSendStreamImpl::SetTransportOverhead(
672 size_t transport_overhead_bytes_per_packet) {
673 if (transport_overhead_bytes_per_packet >= static_cast<int>(kPathMTU)) {
674 RTC_LOG(LS_ERROR) << "Transport overhead exceeds size of ethernet frame";
675 return;
676 }
677
678 transport_overhead_bytes_per_packet_ = transport_overhead_bytes_per_packet;
679
680 size_t rtp_packet_size =
681 std::min(config_->rtp.max_packet_size,
682 kPathMTU - transport_overhead_bytes_per_packet_);
683
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200684 payload_router_->SetMaxRtpPacketSize(rtp_packet_size);
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +0200685}
686
687void VideoSendStreamImpl::OnPacketAdded(uint32_t ssrc, uint16_t seq_num) {
688 if (!worker_queue_->IsCurrent()) {
689 auto ptr = weak_ptr_;
690 worker_queue_->PostTask([=] {
691 if (!ptr.get())
692 return;
693 ptr->OnPacketAdded(ssrc, seq_num);
694 });
695 return;
696 }
697 const auto ssrcs = config_->rtp.ssrcs;
698 if (std::find(ssrcs.begin(), ssrcs.end(), ssrc) != ssrcs.end()) {
699 feedback_packet_seq_num_set_.insert(seq_num);
700 if (feedback_packet_seq_num_set_.size() > kSendSideSeqNumSetMaxSize) {
701 RTC_LOG(LS_WARNING) << "Feedback packet sequence number set exceed it's "
702 "max size', will get reset.";
703 feedback_packet_seq_num_set_.clear();
704 }
705 }
706}
707
708void VideoSendStreamImpl::OnPacketFeedbackVector(
709 const std::vector<PacketFeedback>& packet_feedback_vector) {
710 if (!worker_queue_->IsCurrent()) {
711 auto ptr = weak_ptr_;
712 worker_queue_->PostTask([=] {
713 if (!ptr.get())
714 return;
715 ptr->OnPacketFeedbackVector(packet_feedback_vector);
716 });
717 return;
718 }
719 // Lost feedbacks are not considered to be lost packets.
720 for (const PacketFeedback& packet : packet_feedback_vector) {
721 if (auto it = feedback_packet_seq_num_set_.find(packet.sequence_number) !=
722 feedback_packet_seq_num_set_.end()) {
723 const bool lost = packet.arrival_time_ms == PacketFeedback::kNotReceived;
724 loss_mask_vector_.push_back(lost);
725 feedback_packet_seq_num_set_.erase(it);
726 }
727 }
728}
729} // namespace internal
730} // namespace webrtc