1 /*
2 * Copyright (c) 2012 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
11 #include "video/video_stream_encoder.h"
12
13 #include <algorithm>
14 #include <array>
15 #include <limits>
16 #include <memory>
17 #include <numeric>
18 #include <utility>
19
20 #include "absl/algorithm/container.h"
21 #include "absl/types/optional.h"
22 #include "api/task_queue/queued_task.h"
23 #include "api/task_queue/task_queue_base.h"
24 #include "api/video/encoded_image.h"
25 #include "api/video/i420_buffer.h"
26 #include "api/video/video_adaptation_reason.h"
27 #include "api/video/video_bitrate_allocator_factory.h"
28 #include "api/video/video_codec_constants.h"
29 #include "api/video_codecs/video_encoder.h"
30 #include "call/adaptation/resource_adaptation_processor.h"
31 #include "call/adaptation/video_stream_adapter.h"
32 #include "modules/video_coding/codecs/vp9/svc_rate_allocator.h"
33 #include "modules/video_coding/include/video_codec_initializer.h"
34 #include "rtc_base/arraysize.h"
35 #include "rtc_base/checks.h"
36 #include "rtc_base/constructor_magic.h"
37 #include "rtc_base/experiments/alr_experiment.h"
38 #include "rtc_base/experiments/rate_control_settings.h"
39 #include "rtc_base/location.h"
40 #include "rtc_base/logging.h"
41 #include "rtc_base/strings/string_builder.h"
42 #include "rtc_base/synchronization/mutex.h"
43 #include "rtc_base/synchronization/sequence_checker.h"
44 #include "rtc_base/thread_annotations.h"
45 #include "rtc_base/time_utils.h"
46 #include "rtc_base/trace_event.h"
47 #include "system_wrappers/include/field_trial.h"
48 #include "video/adaptation/video_stream_encoder_resource_manager.h"
49
50 namespace webrtc {
51
52 namespace {
53
54 // Time interval for logging frame counts.
55 const int64_t kFrameLogIntervalMs = 60000;
56
57 // Time to keep a single cached pending frame in paused state.
58 const int64_t kPendingFrameTimeoutMs = 1000;
59
60 constexpr char kFrameDropperFieldTrial[] = "WebRTC-FrameDropper";
61
62 // Averaging window spanning 90 frames at default 30fps, matching old media
63 // optimization module defaults.
64 const int64_t kFrameRateAvergingWindowSizeMs = (1000 / 30) * 90;
65
66 const size_t kDefaultPayloadSize = 1440;
67
68 const int64_t kParameterUpdateIntervalMs = 1000;
69
70 // Animation is capped to 720p.
71 constexpr int kMaxAnimationPixels = 1280 * 720;
72
RequiresEncoderReset(const VideoCodec & prev_send_codec,const VideoCodec & new_send_codec,bool was_encode_called_since_last_initialization)73 bool RequiresEncoderReset(const VideoCodec& prev_send_codec,
74 const VideoCodec& new_send_codec,
75 bool was_encode_called_since_last_initialization) {
76 // Does not check max/minBitrate or maxFramerate.
77 if (new_send_codec.codecType != prev_send_codec.codecType ||
78 new_send_codec.width != prev_send_codec.width ||
79 new_send_codec.height != prev_send_codec.height ||
80 new_send_codec.qpMax != prev_send_codec.qpMax ||
81 new_send_codec.numberOfSimulcastStreams !=
82 prev_send_codec.numberOfSimulcastStreams ||
83 new_send_codec.mode != prev_send_codec.mode) {
84 return true;
85 }
86
87 if (!was_encode_called_since_last_initialization &&
88 (new_send_codec.startBitrate != prev_send_codec.startBitrate)) {
89 // If start bitrate has changed reconfigure encoder only if encoding had not
90 // yet started.
91 return true;
92 }
93
94 switch (new_send_codec.codecType) {
95 case kVideoCodecVP8:
96 if (new_send_codec.VP8() != prev_send_codec.VP8()) {
97 return true;
98 }
99 break;
100
101 case kVideoCodecVP9:
102 if (new_send_codec.VP9() != prev_send_codec.VP9()) {
103 return true;
104 }
105 break;
106
107 case kVideoCodecH264:
108 if (new_send_codec.H264() != prev_send_codec.H264()) {
109 return true;
110 }
111 break;
112
113 default:
114 break;
115 }
116
117 for (unsigned char i = 0; i < new_send_codec.numberOfSimulcastStreams; ++i) {
118 if (new_send_codec.simulcastStream[i].width !=
119 prev_send_codec.simulcastStream[i].width ||
120 new_send_codec.simulcastStream[i].height !=
121 prev_send_codec.simulcastStream[i].height ||
122 new_send_codec.simulcastStream[i].maxFramerate !=
123 prev_send_codec.simulcastStream[i].maxFramerate ||
124 new_send_codec.simulcastStream[i].numberOfTemporalLayers !=
125 prev_send_codec.simulcastStream[i].numberOfTemporalLayers ||
126 new_send_codec.simulcastStream[i].qpMax !=
127 prev_send_codec.simulcastStream[i].qpMax ||
128 new_send_codec.simulcastStream[i].active !=
129 prev_send_codec.simulcastStream[i].active) {
130 return true;
131 }
132 }
133 return false;
134 }
135
GetExperimentGroups()136 std::array<uint8_t, 2> GetExperimentGroups() {
137 std::array<uint8_t, 2> experiment_groups;
138 absl::optional<AlrExperimentSettings> experiment_settings =
139 AlrExperimentSettings::CreateFromFieldTrial(
140 AlrExperimentSettings::kStrictPacingAndProbingExperimentName);
141 if (experiment_settings) {
142 experiment_groups[0] = experiment_settings->group_id + 1;
143 } else {
144 experiment_groups[0] = 0;
145 }
146 experiment_settings = AlrExperimentSettings::CreateFromFieldTrial(
147 AlrExperimentSettings::kScreenshareProbingBweExperimentName);
148 if (experiment_settings) {
149 experiment_groups[1] = experiment_settings->group_id + 1;
150 } else {
151 experiment_groups[1] = 0;
152 }
153 return experiment_groups;
154 }
155
156 // Limit allocation across TLs in bitrate allocation according to number of TLs
157 // in EncoderInfo.
UpdateAllocationFromEncoderInfo(const VideoBitrateAllocation & allocation,const VideoEncoder::EncoderInfo & encoder_info)158 VideoBitrateAllocation UpdateAllocationFromEncoderInfo(
159 const VideoBitrateAllocation& allocation,
160 const VideoEncoder::EncoderInfo& encoder_info) {
161 if (allocation.get_sum_bps() == 0) {
162 return allocation;
163 }
164 VideoBitrateAllocation new_allocation;
165 for (int si = 0; si < kMaxSpatialLayers; ++si) {
166 if (encoder_info.fps_allocation[si].size() == 1 &&
167 allocation.IsSpatialLayerUsed(si)) {
168 // One TL is signalled to be used by the encoder. Do not distribute
169 // bitrate allocation across TLs (use sum at ti:0).
170 new_allocation.SetBitrate(si, 0, allocation.GetSpatialLayerSum(si));
171 } else {
172 for (int ti = 0; ti < kMaxTemporalStreams; ++ti) {
173 if (allocation.HasBitrate(si, ti))
174 new_allocation.SetBitrate(si, ti, allocation.GetBitrate(si, ti));
175 }
176 }
177 }
178 new_allocation.set_bw_limited(allocation.is_bw_limited());
179 return new_allocation;
180 }
181
182 } // namespace
183
EncoderRateSettings()184 VideoStreamEncoder::EncoderRateSettings::EncoderRateSettings()
185 : rate_control(),
186 encoder_target(DataRate::Zero()),
187 stable_encoder_target(DataRate::Zero()) {}
188
EncoderRateSettings(const VideoBitrateAllocation & bitrate,double framerate_fps,DataRate bandwidth_allocation,DataRate encoder_target,DataRate stable_encoder_target)189 VideoStreamEncoder::EncoderRateSettings::EncoderRateSettings(
190 const VideoBitrateAllocation& bitrate,
191 double framerate_fps,
192 DataRate bandwidth_allocation,
193 DataRate encoder_target,
194 DataRate stable_encoder_target)
195 : rate_control(bitrate, framerate_fps, bandwidth_allocation),
196 encoder_target(encoder_target),
197 stable_encoder_target(stable_encoder_target) {}
198
operator ==(const EncoderRateSettings & rhs) const199 bool VideoStreamEncoder::EncoderRateSettings::operator==(
200 const EncoderRateSettings& rhs) const {
201 return rate_control == rhs.rate_control &&
202 encoder_target == rhs.encoder_target &&
203 stable_encoder_target == rhs.stable_encoder_target;
204 }
205
operator !=(const EncoderRateSettings & rhs) const206 bool VideoStreamEncoder::EncoderRateSettings::operator!=(
207 const EncoderRateSettings& rhs) const {
208 return !(*this == rhs);
209 }
210
211 class VideoStreamEncoder::DegradationPreferenceManager
212 : public DegradationPreferenceProvider {
213 public:
DegradationPreferenceManager()214 DegradationPreferenceManager()
215 : degradation_preference_(DegradationPreference::DISABLED),
216 is_screenshare_(false),
217 effective_degradation_preference_(DegradationPreference::DISABLED) {}
218
~DegradationPreferenceManager()219 ~DegradationPreferenceManager() override {
220 RTC_DCHECK(!video_stream_adapter_);
221 }
222
degradation_preference() const223 DegradationPreference degradation_preference() const override {
224 MutexLock lock(&lock_);
225 return effective_degradation_preference_;
226 }
227
SetDegradationPreference(DegradationPreference degradation_preference)228 void SetDegradationPreference(DegradationPreference degradation_preference) {
229 MutexLock lock(&lock_);
230 degradation_preference_ = degradation_preference;
231 MaybeUpdateEffectiveDegradationPreference();
232 }
233
SetIsScreenshare(bool is_screenshare)234 void SetIsScreenshare(bool is_screenshare) {
235 MutexLock lock(&lock_);
236 is_screenshare_ = is_screenshare;
237 MaybeUpdateEffectiveDegradationPreference();
238 }
239
SetVideoStreamAdapterQueue(TaskQueueBase * video_stream_adapter_task_queue)240 void SetVideoStreamAdapterQueue(
241 TaskQueueBase* video_stream_adapter_task_queue) {
242 RTC_DCHECK(!video_stream_adapter_task_queue_);
243 RTC_DCHECK(video_stream_adapter_task_queue);
244 RTC_DCHECK_RUN_ON(video_stream_adapter_task_queue);
245 video_stream_adapter_task_queue_ = video_stream_adapter_task_queue;
246 }
247
SetVideoStreamAdapter(VideoStreamAdapter * video_stream_adapter)248 void SetVideoStreamAdapter(VideoStreamAdapter* video_stream_adapter) {
249 RTC_DCHECK_RUN_ON(video_stream_adapter_task_queue_);
250 video_stream_adapter_ = video_stream_adapter;
251 }
252
253 private:
MaybeUpdateEffectiveDegradationPreference()254 void MaybeUpdateEffectiveDegradationPreference()
255 RTC_EXCLUSIVE_LOCKS_REQUIRED(&lock_) {
256 DegradationPreference effective_degradation_preference =
257 (is_screenshare_ &&
258 degradation_preference_ == DegradationPreference::BALANCED)
259 ? DegradationPreference::MAINTAIN_RESOLUTION
260 : degradation_preference_;
261
262 if (effective_degradation_preference != effective_degradation_preference_) {
263 effective_degradation_preference_ = effective_degradation_preference;
264 if (video_stream_adapter_task_queue_) {
265 video_stream_adapter_task_queue_->PostTask(
266 ToQueuedTask([this, effective_degradation_preference]() {
267 RTC_DCHECK_RUN_ON(video_stream_adapter_task_queue_);
268 if (video_stream_adapter_) {
269 video_stream_adapter_->SetDegradationPreference(
270 effective_degradation_preference);
271 }
272 }));
273 }
274 }
275 }
276
277 mutable Mutex lock_;
278 DegradationPreference degradation_preference_ RTC_GUARDED_BY(&lock_);
279 bool is_screenshare_ RTC_GUARDED_BY(&lock_);
280 DegradationPreference effective_degradation_preference_
281 RTC_GUARDED_BY(&lock_);
282 TaskQueueBase* video_stream_adapter_task_queue_ = nullptr;
283 VideoStreamAdapter* video_stream_adapter_
284 RTC_GUARDED_BY(&video_stream_adapter_task_queue_);
285 };
286
VideoStreamEncoder(Clock * clock,uint32_t number_of_cores,VideoStreamEncoderObserver * encoder_stats_observer,const VideoStreamEncoderSettings & settings,std::unique_ptr<OveruseFrameDetector> overuse_detector,TaskQueueFactory * task_queue_factory)287 VideoStreamEncoder::VideoStreamEncoder(
288 Clock* clock,
289 uint32_t number_of_cores,
290 VideoStreamEncoderObserver* encoder_stats_observer,
291 const VideoStreamEncoderSettings& settings,
292 std::unique_ptr<OveruseFrameDetector> overuse_detector,
293 TaskQueueFactory* task_queue_factory)
294 : shutdown_event_(true /* manual_reset */, false),
295 number_of_cores_(number_of_cores),
296 quality_scaling_experiment_enabled_(QualityScalingExperiment::Enabled()),
297 sink_(nullptr),
298 settings_(settings),
299 rate_control_settings_(RateControlSettings::ParseFromFieldTrials()),
300 encoder_selector_(settings.encoder_factory->GetEncoderSelector()),
301 encoder_stats_observer_(encoder_stats_observer),
302 encoder_initialized_(false),
303 max_framerate_(-1),
304 pending_encoder_reconfiguration_(false),
305 pending_encoder_creation_(false),
306 crop_width_(0),
307 crop_height_(0),
308 encoder_target_bitrate_bps_(absl::nullopt),
309 max_data_payload_length_(0),
310 encoder_paused_and_dropped_frame_(false),
311 was_encode_called_since_last_initialization_(false),
312 encoder_failed_(false),
313 clock_(clock),
314 posted_frames_waiting_for_encode_(0),
315 last_captured_timestamp_(0),
316 delta_ntp_internal_ms_(clock_->CurrentNtpInMilliseconds() -
317 clock_->TimeInMilliseconds()),
318 last_frame_log_ms_(clock_->TimeInMilliseconds()),
319 captured_frame_count_(0),
320 dropped_frame_cwnd_pushback_count_(0),
321 dropped_frame_encoder_block_count_(0),
322 pending_frame_post_time_us_(0),
323 accumulated_update_rect_{0, 0, 0, 0},
324 accumulated_update_rect_is_valid_(true),
325 animation_start_time_(Timestamp::PlusInfinity()),
326 cap_resolution_due_to_video_content_(false),
327 expect_resize_state_(ExpectResizeState::kNoResize),
328 bitrate_observer_(nullptr),
329 fec_controller_override_(nullptr),
330 force_disable_frame_dropper_(false),
331 input_framerate_(kFrameRateAvergingWindowSizeMs, 1000),
332 pending_frame_drops_(0),
333 cwnd_frame_counter_(0),
334 next_frame_types_(1, VideoFrameType::kVideoFrameDelta),
335 frame_encode_metadata_writer_(this),
336 experiment_groups_(GetExperimentGroups()),
337 encoder_switch_experiment_(ParseEncoderSwitchFieldTrial()),
338 automatic_animation_detection_experiment_(
339 ParseAutomatincAnimationDetectionFieldTrial()),
340 encoder_switch_requested_(false),
341 input_state_provider_(encoder_stats_observer),
342 video_stream_adapter_(
343 std::make_unique<VideoStreamAdapter>(&input_state_provider_)),
344 resource_adaptation_processor_(
345 std::make_unique<ResourceAdaptationProcessor>(
346 encoder_stats_observer,
347 video_stream_adapter_.get())),
348 degradation_preference_manager_(
349 std::make_unique<DegradationPreferenceManager>()),
350 adaptation_constraints_(),
351 stream_resource_manager_(&input_state_provider_,
352 encoder_stats_observer,
353 clock_,
354 settings_.experiment_cpu_load_estimator,
355 std::move(overuse_detector),
356 degradation_preference_manager_.get()),
357 video_source_sink_controller_(/*sink=*/this,
358 /*source=*/nullptr),
359 resource_adaptation_queue_(task_queue_factory->CreateTaskQueue(
360 "ResourceAdaptationQueue",
361 TaskQueueFactory::Priority::NORMAL)),
362 encoder_queue_(task_queue_factory->CreateTaskQueue(
363 "EncoderQueue",
364 TaskQueueFactory::Priority::NORMAL)) {
365 RTC_DCHECK(encoder_stats_observer);
366 RTC_DCHECK_GE(number_of_cores, 1);
367
368 stream_resource_manager_.Initialize(&encoder_queue_,
369 &resource_adaptation_queue_);
370
371 rtc::Event initialize_processor_event;
__anon9322e9290302null372 resource_adaptation_queue_.PostTask([this, &initialize_processor_event] {
373 RTC_DCHECK_RUN_ON(&resource_adaptation_queue_);
374 resource_adaptation_processor_->SetResourceAdaptationQueue(
375 resource_adaptation_queue_.Get());
376 stream_resource_manager_.SetAdaptationProcessor(
377 resource_adaptation_processor_.get(), video_stream_adapter_.get());
378 resource_adaptation_processor_->AddResourceLimitationsListener(
379 &stream_resource_manager_);
380 video_stream_adapter_->AddRestrictionsListener(&stream_resource_manager_);
381 video_stream_adapter_->AddRestrictionsListener(this);
382 degradation_preference_manager_->SetVideoStreamAdapterQueue(
383 resource_adaptation_queue_.Get());
384 degradation_preference_manager_->SetVideoStreamAdapter(
385 video_stream_adapter_.get());
386
387 // Add the stream resource manager's resources to the processor.
388 adaptation_constraints_ = stream_resource_manager_.AdaptationConstraints();
389 for (auto& resource : stream_resource_manager_.MappedResources()) {
390 resource_adaptation_processor_->AddResource(resource);
391 }
392 for (auto* constraint : adaptation_constraints_) {
393 video_stream_adapter_->AddAdaptationConstraint(constraint);
394 }
395 for (auto* listener : stream_resource_manager_.AdaptationListeners()) {
396 video_stream_adapter_->AddAdaptationListener(listener);
397 }
398 initialize_processor_event.Set();
399 });
400 initialize_processor_event.Wait(rtc::Event::kForever);
401 }
402
~VideoStreamEncoder()403 VideoStreamEncoder::~VideoStreamEncoder() {
404 RTC_DCHECK_RUN_ON(&thread_checker_);
405 RTC_DCHECK(shutdown_event_.Wait(0))
406 << "Must call ::Stop() before destruction.";
407 }
408
Stop()409 void VideoStreamEncoder::Stop() {
410 RTC_DCHECK_RUN_ON(&thread_checker_);
411 video_source_sink_controller_.SetSource(nullptr);
412
413 if (resource_adaptation_processor_) {
414 for (auto& resource : stream_resource_manager_.MappedResources()) {
415 resource_adaptation_processor_->RemoveResource(resource);
416 }
417 }
418 rtc::Event shutdown_adaptation_processor_event;
419 resource_adaptation_queue_.PostTask([this,
420 &shutdown_adaptation_processor_event] {
421 RTC_DCHECK_RUN_ON(&resource_adaptation_queue_);
422 if (resource_adaptation_processor_) {
423 // Removed on the resource_adaptaiton_processor_ queue because the
424 // adaptation_constraints_ and adaptation_listeners_ fields are guarded by
425 // this queue.
426 for (auto* constraint : adaptation_constraints_) {
427 video_stream_adapter_->RemoveAdaptationConstraint(constraint);
428 }
429 for (auto* listener : stream_resource_manager_.AdaptationListeners()) {
430 video_stream_adapter_->RemoveAdaptationListener(listener);
431 }
432 video_stream_adapter_->RemoveRestrictionsListener(this);
433 video_stream_adapter_->RemoveRestrictionsListener(
434 &stream_resource_manager_);
435 resource_adaptation_processor_->RemoveResourceLimitationsListener(
436 &stream_resource_manager_);
437 stream_resource_manager_.SetAdaptationProcessor(nullptr, nullptr);
438 degradation_preference_manager_->SetVideoStreamAdapter(nullptr);
439 resource_adaptation_processor_.reset();
440 }
441 shutdown_adaptation_processor_event.Set();
442 });
443 shutdown_adaptation_processor_event.Wait(rtc::Event::kForever);
444 encoder_queue_.PostTask([this] {
445 RTC_DCHECK_RUN_ON(&encoder_queue_);
446 stream_resource_manager_.StopManagedResources();
447 rate_allocator_ = nullptr;
448 bitrate_observer_ = nullptr;
449 ReleaseEncoder();
450 shutdown_event_.Set();
451 });
452 shutdown_event_.Wait(rtc::Event::kForever);
453 }
454
SetBitrateAllocationObserver(VideoBitrateAllocationObserver * bitrate_observer)455 void VideoStreamEncoder::SetBitrateAllocationObserver(
456 VideoBitrateAllocationObserver* bitrate_observer) {
457 RTC_DCHECK_RUN_ON(&thread_checker_);
458 encoder_queue_.PostTask([this, bitrate_observer] {
459 RTC_DCHECK_RUN_ON(&encoder_queue_);
460 RTC_DCHECK(!bitrate_observer_);
461 bitrate_observer_ = bitrate_observer;
462 });
463 }
464
SetFecControllerOverride(FecControllerOverride * fec_controller_override)465 void VideoStreamEncoder::SetFecControllerOverride(
466 FecControllerOverride* fec_controller_override) {
467 encoder_queue_.PostTask([this, fec_controller_override] {
468 RTC_DCHECK_RUN_ON(&encoder_queue_);
469 RTC_DCHECK(!fec_controller_override_);
470 fec_controller_override_ = fec_controller_override;
471 if (encoder_) {
472 encoder_->SetFecControllerOverride(fec_controller_override_);
473 }
474 });
475 }
476
AddAdaptationResource(rtc::scoped_refptr<Resource> resource)477 void VideoStreamEncoder::AddAdaptationResource(
478 rtc::scoped_refptr<Resource> resource) {
479 // Map any externally added resources as kCpu for the sake of stats reporting.
480 // TODO(hbos): Make the manager map any unknown resources to kCpu and get rid
481 // of this MapResourceToReason() call.
482 rtc::Event map_resource_event;
483 encoder_queue_.PostTask([this, resource, &map_resource_event] {
484 RTC_DCHECK_RUN_ON(&encoder_queue_);
485 stream_resource_manager_.MapResourceToReason(resource,
486 VideoAdaptationReason::kCpu);
487 resource_adaptation_processor_->AddResource(resource);
488 map_resource_event.Set();
489 });
490 map_resource_event.Wait(rtc::Event::kForever);
491 }
492
493 std::vector<rtc::scoped_refptr<Resource>>
GetAdaptationResources()494 VideoStreamEncoder::GetAdaptationResources() {
495 return resource_adaptation_processor_->GetResources();
496 }
497
SetSource(rtc::VideoSourceInterface<VideoFrame> * source,const DegradationPreference & degradation_preference)498 void VideoStreamEncoder::SetSource(
499 rtc::VideoSourceInterface<VideoFrame>* source,
500 const DegradationPreference& degradation_preference) {
501 RTC_DCHECK_RUN_ON(&thread_checker_);
502 video_source_sink_controller_.SetSource(source);
503 input_state_provider_.OnHasInputChanged(source);
504
505 degradation_preference_manager_->SetDegradationPreference(
506 degradation_preference);
507 // This may trigger reconfiguring the QualityScaler on the encoder queue.
508 encoder_queue_.PostTask([this, degradation_preference] {
509 RTC_DCHECK_RUN_ON(&encoder_queue_);
510 stream_resource_manager_.SetDegradationPreferences(degradation_preference);
511 if (encoder_) {
512 stream_resource_manager_.ConfigureQualityScaler(
513 encoder_->GetEncoderInfo());
514 }
515 });
516 }
517
SetSink(EncoderSink * sink,bool rotation_applied)518 void VideoStreamEncoder::SetSink(EncoderSink* sink, bool rotation_applied) {
519 video_source_sink_controller_.SetRotationApplied(rotation_applied);
520 video_source_sink_controller_.PushSourceSinkSettings();
521 encoder_queue_.PostTask([this, sink] {
522 RTC_DCHECK_RUN_ON(&encoder_queue_);
523 sink_ = sink;
524 });
525 }
526
SetStartBitrate(int start_bitrate_bps)527 void VideoStreamEncoder::SetStartBitrate(int start_bitrate_bps) {
528 encoder_queue_.PostTask([this, start_bitrate_bps] {
529 RTC_DCHECK_RUN_ON(&encoder_queue_);
530 encoder_target_bitrate_bps_ =
531 start_bitrate_bps != 0 ? absl::optional<uint32_t>(start_bitrate_bps)
532 : absl::nullopt;
533 stream_resource_manager_.SetStartBitrate(
534 DataRate::BitsPerSec(start_bitrate_bps));
535 });
536 }
537
ConfigureEncoder(VideoEncoderConfig config,size_t max_data_payload_length)538 void VideoStreamEncoder::ConfigureEncoder(VideoEncoderConfig config,
539 size_t max_data_payload_length) {
540 encoder_queue_.PostTask(
541 [this, config = std::move(config), max_data_payload_length]() mutable {
542 RTC_DCHECK_RUN_ON(&encoder_queue_);
543 RTC_DCHECK(sink_);
544 RTC_LOG(LS_INFO) << "ConfigureEncoder requested.";
545
546 pending_encoder_creation_ =
547 (!encoder_ || encoder_config_.video_format != config.video_format ||
548 max_data_payload_length_ != max_data_payload_length);
549 encoder_config_ = std::move(config);
550 max_data_payload_length_ = max_data_payload_length;
551 pending_encoder_reconfiguration_ = true;
552
553 // Reconfigure the encoder now if the encoder has an internal source or
554 // if the frame resolution is known. Otherwise, the reconfiguration is
555 // deferred until the next frame to minimize the number of
556 // reconfigurations. The codec configuration depends on incoming video
557 // frame size.
558 if (last_frame_info_) {
559 ReconfigureEncoder();
560 } else {
561 codec_info_ = settings_.encoder_factory->QueryVideoEncoder(
562 encoder_config_.video_format);
563 if (HasInternalSource()) {
564 last_frame_info_ = VideoFrameInfo(kDefaultInputPixelsWidth,
565 kDefaultInputPixelsHeight, false);
566 ReconfigureEncoder();
567 }
568 }
569 });
570 }
571
572 // TODO(bugs.webrtc.org/8807): Currently this always does a hard
573 // reconfiguration, but this isn't always necessary. Add in logic to only update
574 // the VideoBitrateAllocator and call OnEncoderConfigurationChanged with a
575 // "soft" reconfiguration.
ReconfigureEncoder()576 void VideoStreamEncoder::ReconfigureEncoder() {
577 RTC_DCHECK(pending_encoder_reconfiguration_);
578
579 if (!encoder_selector_ &&
580 encoder_switch_experiment_.IsPixelCountBelowThreshold(
581 last_frame_info_->width * last_frame_info_->height) &&
582 !encoder_switch_requested_ && settings_.encoder_switch_request_callback) {
583 EncoderSwitchRequestCallback::Config conf;
584 conf.codec_name = encoder_switch_experiment_.to_codec;
585 conf.param = encoder_switch_experiment_.to_param;
586 conf.value = encoder_switch_experiment_.to_value;
587 settings_.encoder_switch_request_callback->RequestEncoderSwitch(conf);
588
589 encoder_switch_requested_ = true;
590 }
591
592 std::vector<VideoStream> streams =
593 encoder_config_.video_stream_factory->CreateEncoderStreams(
594 last_frame_info_->width, last_frame_info_->height, encoder_config_);
595
596 // Check that the higher layers do not try to set number of temporal layers
597 // to less than 1.
598 // TODO(brandtr): Get rid of the wrapping optional as it serves no purpose
599 // at this layer.
600 #if RTC_DCHECK_IS_ON
601 for (const auto& stream : streams) {
602 RTC_DCHECK_GE(stream.num_temporal_layers.value_or(1), 1);
603 }
604 #endif
605
606 // TODO(ilnik): If configured resolution is significantly less than provided,
607 // e.g. because there are not enough SSRCs for all simulcast streams,
608 // signal new resolutions via SinkWants to video source.
609
610 // Stream dimensions may be not equal to given because of a simulcast
611 // restrictions.
612 auto highest_stream = absl::c_max_element(
613 streams, [](const webrtc::VideoStream& a, const webrtc::VideoStream& b) {
614 return std::tie(a.width, a.height) < std::tie(b.width, b.height);
615 });
616 int highest_stream_width = static_cast<int>(highest_stream->width);
617 int highest_stream_height = static_cast<int>(highest_stream->height);
618 // Dimension may be reduced to be, e.g. divisible by 4.
619 RTC_CHECK_GE(last_frame_info_->width, highest_stream_width);
620 RTC_CHECK_GE(last_frame_info_->height, highest_stream_height);
621 crop_width_ = last_frame_info_->width - highest_stream_width;
622 crop_height_ = last_frame_info_->height - highest_stream_height;
623
624 bool encoder_reset_required = false;
625 if (pending_encoder_creation_) {
626 // Destroy existing encoder instance before creating a new one. Otherwise
627 // attempt to create another instance will fail if encoder factory
628 // supports only single instance of encoder of given type.
629 encoder_.reset();
630
631 encoder_ = settings_.encoder_factory->CreateVideoEncoder(
632 encoder_config_.video_format);
633 // TODO(nisse): What to do if creating the encoder fails? Crash,
634 // or just discard incoming frames?
635 RTC_CHECK(encoder_);
636
637 if (encoder_selector_) {
638 encoder_selector_->OnCurrentEncoder(encoder_config_.video_format);
639 }
640
641 encoder_->SetFecControllerOverride(fec_controller_override_);
642
643 codec_info_ = settings_.encoder_factory->QueryVideoEncoder(
644 encoder_config_.video_format);
645
646 encoder_reset_required = true;
647 }
648
649 encoder_bitrate_limits_ =
650 encoder_->GetEncoderInfo().GetEncoderBitrateLimitsForResolution(
651 last_frame_info_->width * last_frame_info_->height);
652
653 if (streams.size() == 1 && encoder_bitrate_limits_) {
654 // Bitrate limits can be set by app (in SDP or RtpEncodingParameters) or/and
655 // can be provided by encoder. In presence of both set of limits, the final
656 // set is derived as their intersection.
657 int min_bitrate_bps;
658 if (encoder_config_.simulcast_layers.empty() ||
659 encoder_config_.simulcast_layers[0].min_bitrate_bps <= 0) {
660 min_bitrate_bps = encoder_bitrate_limits_->min_bitrate_bps;
661 } else {
662 min_bitrate_bps = std::max(encoder_bitrate_limits_->min_bitrate_bps,
663 streams.back().min_bitrate_bps);
664 }
665
666 int max_bitrate_bps;
667 // We don't check encoder_config_.simulcast_layers[0].max_bitrate_bps
668 // here since encoder_config_.max_bitrate_bps is derived from it (as
669 // well as from other inputs).
670 if (encoder_config_.max_bitrate_bps <= 0) {
671 max_bitrate_bps = encoder_bitrate_limits_->max_bitrate_bps;
672 } else {
673 max_bitrate_bps = std::min(encoder_bitrate_limits_->max_bitrate_bps,
674 streams.back().max_bitrate_bps);
675 }
676
677 if (min_bitrate_bps < max_bitrate_bps) {
678 streams.back().min_bitrate_bps = min_bitrate_bps;
679 streams.back().max_bitrate_bps = max_bitrate_bps;
680 streams.back().target_bitrate_bps =
681 std::min(streams.back().target_bitrate_bps,
682 encoder_bitrate_limits_->max_bitrate_bps);
683 } else {
684 RTC_LOG(LS_WARNING) << "Bitrate limits provided by encoder"
685 << " (min="
686 << encoder_bitrate_limits_->min_bitrate_bps
687 << ", max="
688 << encoder_bitrate_limits_->min_bitrate_bps
689 << ") do not intersect with limits set by app"
690 << " (min=" << streams.back().min_bitrate_bps
691 << ", max=" << encoder_config_.max_bitrate_bps
692 << "). The app bitrate limits will be used.";
693 }
694 }
695
696 VideoCodec codec;
697 if (!VideoCodecInitializer::SetupCodec(encoder_config_, streams, &codec)) {
698 RTC_LOG(LS_ERROR) << "Failed to create encoder configuration.";
699 }
700
701 if (encoder_config_.codec_type == kVideoCodecVP9) {
702 // Spatial layers configuration might impose some parity restrictions,
703 // thus some cropping might be needed.
704 crop_width_ = last_frame_info_->width - codec.width;
705 crop_height_ = last_frame_info_->height - codec.height;
706 }
707
708 char log_stream_buf[4 * 1024];
709 rtc::SimpleStringBuilder log_stream(log_stream_buf);
710 log_stream << "ReconfigureEncoder:\n";
711 log_stream << "Simulcast streams:\n";
712 for (size_t i = 0; i < codec.numberOfSimulcastStreams; ++i) {
713 log_stream << i << ": " << codec.simulcastStream[i].width << "x"
714 << codec.simulcastStream[i].height
715 << " fps: " << codec.simulcastStream[i].maxFramerate
716 << " min_kbps: " << codec.simulcastStream[i].minBitrate
717 << " target_kbps: " << codec.simulcastStream[i].targetBitrate
718 << " max_kbps: " << codec.simulcastStream[i].maxBitrate
719 << " max_fps: " << codec.simulcastStream[i].maxFramerate
720 << " max_qp: " << codec.simulcastStream[i].qpMax
721 << " num_tl: " << codec.simulcastStream[i].numberOfTemporalLayers
722 << " active: "
723 << (codec.simulcastStream[i].active ? "true" : "false") << "\n";
724 }
725 if (encoder_config_.codec_type == kVideoCodecVP9) {
726 size_t num_spatial_layers = codec.VP9()->numberOfSpatialLayers;
727 log_stream << "Spatial layers:\n";
728 for (size_t i = 0; i < num_spatial_layers; ++i) {
729 log_stream << i << ": " << codec.spatialLayers[i].width << "x"
730 << codec.spatialLayers[i].height
731 << " fps: " << codec.spatialLayers[i].maxFramerate
732 << " min_kbps: " << codec.spatialLayers[i].minBitrate
733 << " target_kbps: " << codec.spatialLayers[i].targetBitrate
734 << " max_kbps: " << codec.spatialLayers[i].maxBitrate
735 << " max_qp: " << codec.spatialLayers[i].qpMax
736 << " num_tl: " << codec.spatialLayers[i].numberOfTemporalLayers
737 << " active: "
738 << (codec.spatialLayers[i].active ? "true" : "false") << "\n";
739 }
740 }
741 RTC_LOG(LS_INFO) << log_stream.str();
742
743 codec.startBitrate = std::max(encoder_target_bitrate_bps_.value_or(0) / 1000,
744 codec.minBitrate);
745 codec.startBitrate = std::min(codec.startBitrate, codec.maxBitrate);
746 codec.expect_encode_from_texture = last_frame_info_->is_texture;
747 // Make sure the start bit rate is sane...
748 RTC_DCHECK_LE(codec.startBitrate, 1000000);
749 max_framerate_ = codec.maxFramerate;
750
751 // Inform source about max configured framerate.
752 int max_framerate = 0;
753 for (const auto& stream : streams) {
754 max_framerate = std::max(stream.max_framerate, max_framerate);
755 }
756 int alignment = encoder_->GetEncoderInfo().requested_resolution_alignment;
757 if (max_framerate != video_source_sink_controller_.frame_rate_upper_limit() ||
758 alignment != video_source_sink_controller_.resolution_alignment()) {
759 video_source_sink_controller_.SetFrameRateUpperLimit(max_framerate);
760 video_source_sink_controller_.SetResolutionAlignment(alignment);
761 video_source_sink_controller_.PushSourceSinkSettings();
762 }
763
764 if (codec.maxBitrate == 0) {
765 // max is one bit per pixel
766 codec.maxBitrate =
767 (static_cast<int>(codec.height) * static_cast<int>(codec.width) *
768 static_cast<int>(codec.maxFramerate)) /
769 1000;
770 if (codec.startBitrate > codec.maxBitrate) {
771 // But if the user tries to set a higher start bit rate we will
772 // increase the max accordingly.
773 codec.maxBitrate = codec.startBitrate;
774 }
775 }
776
777 if (codec.startBitrate > codec.maxBitrate) {
778 codec.startBitrate = codec.maxBitrate;
779 }
780
781 rate_allocator_ =
782 settings_.bitrate_allocator_factory->CreateVideoBitrateAllocator(codec);
783
784 // Reset (release existing encoder) if one exists and anything except
785 // start bitrate or max framerate has changed.
786 if (!encoder_reset_required) {
787 encoder_reset_required = RequiresEncoderReset(
788 codec, send_codec_, was_encode_called_since_last_initialization_);
789 }
790 send_codec_ = codec;
791
792 encoder_switch_experiment_.SetCodec(send_codec_.codecType);
793
794 // Keep the same encoder, as long as the video_format is unchanged.
795 // Encoder creation block is split in two since EncoderInfo needed to start
796 // CPU adaptation with the correct settings should be polled after
797 // encoder_->InitEncode().
798 bool success = true;
799 if (encoder_reset_required) {
800 ReleaseEncoder();
801 const size_t max_data_payload_length = max_data_payload_length_ > 0
802 ? max_data_payload_length_
803 : kDefaultPayloadSize;
804 if (encoder_->InitEncode(
805 &send_codec_,
806 VideoEncoder::Settings(settings_.capabilities, number_of_cores_,
807 max_data_payload_length)) != 0) {
808 RTC_LOG(LS_ERROR) << "Failed to initialize the encoder associated with "
809 "codec type: "
810 << CodecTypeToPayloadString(send_codec_.codecType)
811 << " (" << send_codec_.codecType << ")";
812 ReleaseEncoder();
813 success = false;
814 } else {
815 encoder_initialized_ = true;
816 encoder_->RegisterEncodeCompleteCallback(this);
817 frame_encode_metadata_writer_.OnEncoderInit(send_codec_,
818 HasInternalSource());
819 }
820
821 frame_encode_metadata_writer_.Reset();
822 last_encode_info_ms_ = absl::nullopt;
823 was_encode_called_since_last_initialization_ = false;
824 }
825
826 // Inform dependents of updated encoder settings.
827 OnEncoderSettingsChanged();
828
829 if (success) {
830 next_frame_types_.clear();
831 next_frame_types_.resize(
832 std::max(static_cast<int>(codec.numberOfSimulcastStreams), 1),
833 VideoFrameType::kVideoFrameKey);
834 RTC_LOG(LS_VERBOSE) << " max bitrate " << codec.maxBitrate
835 << " start bitrate " << codec.startBitrate
836 << " max frame rate " << codec.maxFramerate
837 << " max payload size " << max_data_payload_length_;
838 } else {
839 RTC_LOG(LS_ERROR) << "Failed to configure encoder.";
840 rate_allocator_ = nullptr;
841 }
842
843 if (pending_encoder_creation_) {
844 // TODO(hbos): Stopping and restarting for backwards compatibility reasons.
845 // We may be able to change this to "EnsureStarted()" if it took care of
846 // reconfiguring the QualityScaler as well. (ConfigureQualityScaler() is
847 // invoked later in this method.)
848 stream_resource_manager_.StopManagedResources();
849 stream_resource_manager_.StartEncodeUsageResource();
850 pending_encoder_creation_ = false;
851 }
852
853 int num_layers;
854 if (codec.codecType == kVideoCodecVP8) {
855 num_layers = codec.VP8()->numberOfTemporalLayers;
856 } else if (codec.codecType == kVideoCodecVP9) {
857 num_layers = codec.VP9()->numberOfTemporalLayers;
858 } else if (codec.codecType == kVideoCodecH264) {
859 num_layers = codec.H264()->numberOfTemporalLayers;
860 } else if (codec.codecType == kVideoCodecGeneric &&
861 codec.numberOfSimulcastStreams > 0) {
862 // This is mainly for unit testing, disabling frame dropping.
863 // TODO(sprang): Add a better way to disable frame dropping.
864 num_layers = codec.simulcastStream[0].numberOfTemporalLayers;
865 } else {
866 num_layers = 1;
867 }
868
869 frame_dropper_.Reset();
870 frame_dropper_.SetRates(codec.startBitrate, max_framerate_);
871 // Force-disable frame dropper if either:
872 // * We have screensharing with layers.
873 // * "WebRTC-FrameDropper" field trial is "Disabled".
874 force_disable_frame_dropper_ =
875 field_trial::IsDisabled(kFrameDropperFieldTrial) ||
876 (num_layers > 1 && codec.mode == VideoCodecMode::kScreensharing);
877
878 VideoEncoder::EncoderInfo info = encoder_->GetEncoderInfo();
879 if (rate_control_settings_.UseEncoderBitrateAdjuster()) {
880 bitrate_adjuster_ = std::make_unique<EncoderBitrateAdjuster>(codec);
881 bitrate_adjuster_->OnEncoderInfo(info);
882 }
883
884 if (rate_allocator_ && last_encoder_rate_settings_) {
885 // We have a new rate allocator instance and already configured target
886 // bitrate. Update the rate allocation and notify observers.
887 // We must invalidate the last_encoder_rate_settings_ to ensure
888 // the changes get propagated to all listeners.
889 EncoderRateSettings rate_settings = *last_encoder_rate_settings_;
890 last_encoder_rate_settings_.reset();
891 rate_settings.rate_control.framerate_fps = GetInputFramerateFps();
892
893 SetEncoderRates(UpdateBitrateAllocationAndNotifyObserver(rate_settings));
894 }
895
896 encoder_stats_observer_->OnEncoderReconfigured(encoder_config_, streams);
897
898 pending_encoder_reconfiguration_ = false;
899
900 bool is_svc = false;
901 // Set min_bitrate_bps, max_bitrate_bps, and max padding bit rate for VP9
902 // and leave only one stream containing all necessary information.
903 if (encoder_config_.codec_type == kVideoCodecVP9) {
904 // Lower max bitrate to the level codec actually can produce.
905 streams[0].max_bitrate_bps =
906 std::min(streams[0].max_bitrate_bps,
907 SvcRateAllocator::GetMaxBitrate(codec).bps<int>());
908 streams[0].min_bitrate_bps = codec.spatialLayers[0].minBitrate * 1000;
909 // target_bitrate_bps specifies the maximum padding bitrate.
910 streams[0].target_bitrate_bps =
911 SvcRateAllocator::GetPaddingBitrate(codec).bps<int>();
912 streams[0].width = streams.back().width;
913 streams[0].height = streams.back().height;
914 is_svc = codec.VP9()->numberOfSpatialLayers > 1;
915 streams.resize(1);
916 }
917
918 sink_->OnEncoderConfigurationChanged(
919 std::move(streams), is_svc, encoder_config_.content_type,
920 encoder_config_.min_transmit_bitrate_bps);
921
922 stream_resource_manager_.ConfigureQualityScaler(info);
923 }
924
OnEncoderSettingsChanged()925 void VideoStreamEncoder::OnEncoderSettingsChanged() {
926 EncoderSettings encoder_settings(encoder_->GetEncoderInfo(),
927 encoder_config_.Copy(), send_codec_);
928 stream_resource_manager_.SetEncoderSettings(encoder_settings);
929 input_state_provider_.OnEncoderSettingsChanged(encoder_settings);
930 bool is_screenshare = encoder_settings.encoder_config().content_type ==
931 VideoEncoderConfig::ContentType::kScreen;
932 degradation_preference_manager_->SetIsScreenshare(is_screenshare);
933 }
934
OnFrame(const VideoFrame & video_frame)935 void VideoStreamEncoder::OnFrame(const VideoFrame& video_frame) {
936 RTC_DCHECK_RUNS_SERIALIZED(&incoming_frame_race_checker_);
937 VideoFrame incoming_frame = video_frame;
938
939 // Local time in webrtc time base.
940 int64_t current_time_us = clock_->TimeInMicroseconds();
941 int64_t current_time_ms = current_time_us / rtc::kNumMicrosecsPerMillisec;
942 // In some cases, e.g., when the frame from decoder is fed to encoder,
943 // the timestamp may be set to the future. As the encoding pipeline assumes
944 // capture time to be less than present time, we should reset the capture
945 // timestamps here. Otherwise there may be issues with RTP send stream.
946 if (incoming_frame.timestamp_us() > current_time_us)
947 incoming_frame.set_timestamp_us(current_time_us);
948
949 // Capture time may come from clock with an offset and drift from clock_.
950 int64_t capture_ntp_time_ms;
951 if (video_frame.ntp_time_ms() > 0) {
952 capture_ntp_time_ms = video_frame.ntp_time_ms();
953 } else if (video_frame.render_time_ms() != 0) {
954 capture_ntp_time_ms = video_frame.render_time_ms() + delta_ntp_internal_ms_;
955 } else {
956 capture_ntp_time_ms = current_time_ms + delta_ntp_internal_ms_;
957 }
958 incoming_frame.set_ntp_time_ms(capture_ntp_time_ms);
959
960 // Convert NTP time, in ms, to RTP timestamp.
961 const int kMsToRtpTimestamp = 90;
962 incoming_frame.set_timestamp(
963 kMsToRtpTimestamp * static_cast<uint32_t>(incoming_frame.ntp_time_ms()));
964
965 if (incoming_frame.ntp_time_ms() <= last_captured_timestamp_) {
966 // We don't allow the same capture time for two frames, drop this one.
967 RTC_LOG(LS_WARNING) << "Same/old NTP timestamp ("
968 << incoming_frame.ntp_time_ms()
969 << " <= " << last_captured_timestamp_
970 << ") for incoming frame. Dropping.";
971 encoder_queue_.PostTask([this, incoming_frame]() {
972 RTC_DCHECK_RUN_ON(&encoder_queue_);
973 accumulated_update_rect_.Union(incoming_frame.update_rect());
974 accumulated_update_rect_is_valid_ &= incoming_frame.has_update_rect();
975 });
976 return;
977 }
978
979 bool log_stats = false;
980 if (current_time_ms - last_frame_log_ms_ > kFrameLogIntervalMs) {
981 last_frame_log_ms_ = current_time_ms;
982 log_stats = true;
983 }
984
985 last_captured_timestamp_ = incoming_frame.ntp_time_ms();
986
987 int64_t post_time_us = rtc::TimeMicros();
988 ++posted_frames_waiting_for_encode_;
989
990 encoder_queue_.PostTask(
991 [this, incoming_frame, post_time_us, log_stats]() {
992 RTC_DCHECK_RUN_ON(&encoder_queue_);
993 encoder_stats_observer_->OnIncomingFrame(incoming_frame.width(),
994 incoming_frame.height());
995 ++captured_frame_count_;
996 const int posted_frames_waiting_for_encode =
997 posted_frames_waiting_for_encode_.fetch_sub(1);
998 RTC_DCHECK_GT(posted_frames_waiting_for_encode, 0);
999 CheckForAnimatedContent(incoming_frame, post_time_us);
1000 bool cwnd_frame_drop =
1001 cwnd_frame_drop_interval_ &&
1002 (cwnd_frame_counter_++ % cwnd_frame_drop_interval_.value() == 0);
1003 if (posted_frames_waiting_for_encode == 1 && !cwnd_frame_drop) {
1004 MaybeEncodeVideoFrame(incoming_frame, post_time_us);
1005 } else {
1006 if (cwnd_frame_drop) {
1007 // Frame drop by congestion window pusback. Do not encode this
1008 // frame.
1009 ++dropped_frame_cwnd_pushback_count_;
1010 encoder_stats_observer_->OnFrameDropped(
1011 VideoStreamEncoderObserver::DropReason::kCongestionWindow);
1012 } else {
1013 // There is a newer frame in flight. Do not encode this frame.
1014 RTC_LOG(LS_VERBOSE)
1015 << "Incoming frame dropped due to that the encoder is blocked.";
1016 ++dropped_frame_encoder_block_count_;
1017 encoder_stats_observer_->OnFrameDropped(
1018 VideoStreamEncoderObserver::DropReason::kEncoderQueue);
1019 }
1020 accumulated_update_rect_.Union(incoming_frame.update_rect());
1021 accumulated_update_rect_is_valid_ &= incoming_frame.has_update_rect();
1022 }
1023 if (log_stats) {
1024 RTC_LOG(LS_INFO) << "Number of frames: captured "
1025 << captured_frame_count_
1026 << ", dropped (due to congestion window pushback) "
1027 << dropped_frame_cwnd_pushback_count_
1028 << ", dropped (due to encoder blocked) "
1029 << dropped_frame_encoder_block_count_
1030 << ", interval_ms " << kFrameLogIntervalMs;
1031 captured_frame_count_ = 0;
1032 dropped_frame_cwnd_pushback_count_ = 0;
1033 dropped_frame_encoder_block_count_ = 0;
1034 }
1035 });
1036 }
1037
OnDiscardedFrame()1038 void VideoStreamEncoder::OnDiscardedFrame() {
1039 encoder_stats_observer_->OnFrameDropped(
1040 VideoStreamEncoderObserver::DropReason::kSource);
1041 }
1042
EncoderPaused() const1043 bool VideoStreamEncoder::EncoderPaused() const {
1044 RTC_DCHECK_RUN_ON(&encoder_queue_);
1045 // Pause video if paused by caller or as long as the network is down or the
1046 // pacer queue has grown too large in buffered mode.
1047 // If the pacer queue has grown too large or the network is down,
1048 // |last_encoder_rate_settings_->encoder_target| will be 0.
1049 return !last_encoder_rate_settings_ ||
1050 last_encoder_rate_settings_->encoder_target == DataRate::Zero();
1051 }
1052
TraceFrameDropStart()1053 void VideoStreamEncoder::TraceFrameDropStart() {
1054 RTC_DCHECK_RUN_ON(&encoder_queue_);
1055 // Start trace event only on the first frame after encoder is paused.
1056 if (!encoder_paused_and_dropped_frame_) {
1057 TRACE_EVENT_ASYNC_BEGIN0("webrtc", "EncoderPaused", this);
1058 }
1059 encoder_paused_and_dropped_frame_ = true;
1060 }
1061
TraceFrameDropEnd()1062 void VideoStreamEncoder::TraceFrameDropEnd() {
1063 RTC_DCHECK_RUN_ON(&encoder_queue_);
1064 // End trace event on first frame after encoder resumes, if frame was dropped.
1065 if (encoder_paused_and_dropped_frame_) {
1066 TRACE_EVENT_ASYNC_END0("webrtc", "EncoderPaused", this);
1067 }
1068 encoder_paused_and_dropped_frame_ = false;
1069 }
1070
1071 VideoStreamEncoder::EncoderRateSettings
UpdateBitrateAllocationAndNotifyObserver(const EncoderRateSettings & rate_settings)1072 VideoStreamEncoder::UpdateBitrateAllocationAndNotifyObserver(
1073 const EncoderRateSettings& rate_settings) {
1074 VideoBitrateAllocation new_allocation;
1075 // Only call allocators if bitrate > 0 (ie, not suspended), otherwise they
1076 // might cap the bitrate to the min bitrate configured.
1077 if (rate_allocator_ && rate_settings.encoder_target > DataRate::Zero()) {
1078 new_allocation = rate_allocator_->Allocate(VideoBitrateAllocationParameters(
1079 rate_settings.encoder_target, rate_settings.stable_encoder_target,
1080 rate_settings.rate_control.framerate_fps));
1081 }
1082
1083 if (bitrate_observer_ && new_allocation.get_sum_bps() > 0) {
1084 if (encoder_ && encoder_initialized_) {
1085 // Avoid too old encoder_info_.
1086 const int64_t kMaxDiffMs = 100;
1087 const bool updated_recently =
1088 (last_encode_info_ms_ && ((clock_->TimeInMilliseconds() -
1089 *last_encode_info_ms_) < kMaxDiffMs));
1090 // Update allocation according to info from encoder.
1091 bitrate_observer_->OnBitrateAllocationUpdated(
1092 UpdateAllocationFromEncoderInfo(
1093 new_allocation,
1094 updated_recently ? encoder_info_ : encoder_->GetEncoderInfo()));
1095 } else {
1096 bitrate_observer_->OnBitrateAllocationUpdated(new_allocation);
1097 }
1098 }
1099
1100 EncoderRateSettings new_rate_settings = rate_settings;
1101 new_rate_settings.rate_control.bitrate = new_allocation;
1102 // VideoBitrateAllocator subclasses may allocate a bitrate higher than the
1103 // target in order to sustain the min bitrate of the video codec. In this
1104 // case, make sure the bandwidth allocation is at least equal the allocation
1105 // as that is part of the document contract for that field.
1106 new_rate_settings.rate_control.bandwidth_allocation =
1107 std::max(new_rate_settings.rate_control.bandwidth_allocation,
1108 DataRate::BitsPerSec(
1109 new_rate_settings.rate_control.bitrate.get_sum_bps()));
1110
1111 if (bitrate_adjuster_) {
1112 VideoBitrateAllocation adjusted_allocation =
1113 bitrate_adjuster_->AdjustRateAllocation(new_rate_settings.rate_control);
1114 RTC_LOG(LS_VERBOSE) << "Adjusting allocation, fps = "
1115 << rate_settings.rate_control.framerate_fps << ", from "
1116 << new_allocation.ToString() << ", to "
1117 << adjusted_allocation.ToString();
1118 new_rate_settings.rate_control.bitrate = adjusted_allocation;
1119 }
1120
1121 encoder_stats_observer_->OnBitrateAllocationUpdated(
1122 send_codec_, new_rate_settings.rate_control.bitrate);
1123
1124 return new_rate_settings;
1125 }
1126
GetInputFramerateFps()1127 uint32_t VideoStreamEncoder::GetInputFramerateFps() {
1128 const uint32_t default_fps = max_framerate_ != -1 ? max_framerate_ : 30;
1129 absl::optional<uint32_t> input_fps =
1130 input_framerate_.Rate(clock_->TimeInMilliseconds());
1131 if (!input_fps || *input_fps == 0) {
1132 return default_fps;
1133 }
1134 return *input_fps;
1135 }
1136
SetEncoderRates(const EncoderRateSettings & rate_settings)1137 void VideoStreamEncoder::SetEncoderRates(
1138 const EncoderRateSettings& rate_settings) {
1139 RTC_DCHECK_GT(rate_settings.rate_control.framerate_fps, 0.0);
1140 bool rate_control_changed =
1141 (!last_encoder_rate_settings_.has_value() ||
1142 last_encoder_rate_settings_->rate_control != rate_settings.rate_control);
1143 if (last_encoder_rate_settings_ != rate_settings) {
1144 last_encoder_rate_settings_ = rate_settings;
1145 }
1146
1147 if (!encoder_) {
1148 return;
1149 }
1150
1151 // |bitrate_allocation| is 0 it means that the network is down or the send
1152 // pacer is full. We currently only report this if the encoder has an internal
1153 // source. If the encoder does not have an internal source, higher levels
1154 // are expected to not call AddVideoFrame. We do this since its unclear
1155 // how current encoder implementations behave when given a zero target
1156 // bitrate.
1157 // TODO(perkj): Make sure all known encoder implementations handle zero
1158 // target bitrate and remove this check.
1159 if (!HasInternalSource() &&
1160 rate_settings.rate_control.bitrate.get_sum_bps() == 0) {
1161 return;
1162 }
1163
1164 if (rate_control_changed) {
1165 encoder_->SetRates(rate_settings.rate_control);
1166 frame_encode_metadata_writer_.OnSetRates(
1167 rate_settings.rate_control.bitrate,
1168 static_cast<uint32_t>(rate_settings.rate_control.framerate_fps + 0.5));
1169 stream_resource_manager_.SetEncoderRates(rate_settings.rate_control);
1170 }
1171 }
1172
MaybeEncodeVideoFrame(const VideoFrame & video_frame,int64_t time_when_posted_us)1173 void VideoStreamEncoder::MaybeEncodeVideoFrame(const VideoFrame& video_frame,
1174 int64_t time_when_posted_us) {
1175 RTC_DCHECK_RUN_ON(&encoder_queue_);
1176 input_state_provider_.OnFrameSizeObserved(video_frame.size());
1177
1178 if (!last_frame_info_ || video_frame.width() != last_frame_info_->width ||
1179 video_frame.height() != last_frame_info_->height ||
1180 video_frame.is_texture() != last_frame_info_->is_texture) {
1181 pending_encoder_reconfiguration_ = true;
1182 last_frame_info_ = VideoFrameInfo(video_frame.width(), video_frame.height(),
1183 video_frame.is_texture());
1184 RTC_LOG(LS_INFO) << "Video frame parameters changed: dimensions="
1185 << last_frame_info_->width << "x"
1186 << last_frame_info_->height
1187 << ", texture=" << last_frame_info_->is_texture << ".";
1188 // Force full frame update, since resolution has changed.
1189 accumulated_update_rect_ =
1190 VideoFrame::UpdateRect{0, 0, video_frame.width(), video_frame.height()};
1191 }
1192
1193 // We have to create then encoder before the frame drop logic,
1194 // because the latter depends on encoder_->GetScalingSettings.
1195 // According to the testcase
1196 // InitialFrameDropOffWhenEncoderDisabledScaling, the return value
1197 // from GetScalingSettings should enable or disable the frame drop.
1198
1199 // Update input frame rate before we start using it. If we update it after
1200 // any potential frame drop we are going to artificially increase frame sizes.
1201 // Poll the rate before updating, otherwise we risk the rate being estimated
1202 // a little too high at the start of the call when then window is small.
1203 uint32_t framerate_fps = GetInputFramerateFps();
1204 input_framerate_.Update(1u, clock_->TimeInMilliseconds());
1205
1206 int64_t now_ms = clock_->TimeInMilliseconds();
1207 if (pending_encoder_reconfiguration_) {
1208 ReconfigureEncoder();
1209 last_parameters_update_ms_.emplace(now_ms);
1210 } else if (!last_parameters_update_ms_ ||
1211 now_ms - *last_parameters_update_ms_ >=
1212 kParameterUpdateIntervalMs) {
1213 if (last_encoder_rate_settings_) {
1214 // Clone rate settings before update, so that SetEncoderRates() will
1215 // actually detect the change between the input and
1216 // |last_encoder_rate_setings_|, triggering the call to SetRate() on the
1217 // encoder.
1218 EncoderRateSettings new_rate_settings = *last_encoder_rate_settings_;
1219 new_rate_settings.rate_control.framerate_fps =
1220 static_cast<double>(framerate_fps);
1221 SetEncoderRates(
1222 UpdateBitrateAllocationAndNotifyObserver(new_rate_settings));
1223 }
1224 last_parameters_update_ms_.emplace(now_ms);
1225 }
1226
1227 // Because pending frame will be dropped in any case, we need to
1228 // remember its updated region.
1229 if (pending_frame_) {
1230 encoder_stats_observer_->OnFrameDropped(
1231 VideoStreamEncoderObserver::DropReason::kEncoderQueue);
1232 accumulated_update_rect_.Union(pending_frame_->update_rect());
1233 accumulated_update_rect_is_valid_ &= pending_frame_->has_update_rect();
1234 }
1235
1236 if (DropDueToSize(video_frame.size())) {
1237 RTC_LOG(LS_INFO) << "Dropping frame. Too large for target bitrate.";
1238 stream_resource_manager_.OnFrameDroppedDueToSize();
1239 // Storing references to a native buffer risks blocking frame capture.
1240 if (video_frame.video_frame_buffer()->type() !=
1241 VideoFrameBuffer::Type::kNative) {
1242 pending_frame_ = video_frame;
1243 pending_frame_post_time_us_ = time_when_posted_us;
1244 } else {
1245 // Ensure that any previously stored frame is dropped.
1246 pending_frame_.reset();
1247 accumulated_update_rect_.Union(video_frame.update_rect());
1248 accumulated_update_rect_is_valid_ &= video_frame.has_update_rect();
1249 }
1250 return;
1251 }
1252 stream_resource_manager_.OnMaybeEncodeFrame();
1253
1254 if (EncoderPaused()) {
1255 // Storing references to a native buffer risks blocking frame capture.
1256 if (video_frame.video_frame_buffer()->type() !=
1257 VideoFrameBuffer::Type::kNative) {
1258 if (pending_frame_)
1259 TraceFrameDropStart();
1260 pending_frame_ = video_frame;
1261 pending_frame_post_time_us_ = time_when_posted_us;
1262 } else {
1263 // Ensure that any previously stored frame is dropped.
1264 pending_frame_.reset();
1265 TraceFrameDropStart();
1266 accumulated_update_rect_.Union(video_frame.update_rect());
1267 accumulated_update_rect_is_valid_ &= video_frame.has_update_rect();
1268 }
1269 return;
1270 }
1271
1272 pending_frame_.reset();
1273
1274 frame_dropper_.Leak(framerate_fps);
1275 // Frame dropping is enabled iff frame dropping is not force-disabled, and
1276 // rate controller is not trusted.
1277 const bool frame_dropping_enabled =
1278 !force_disable_frame_dropper_ &&
1279 !encoder_info_.has_trusted_rate_controller;
1280 frame_dropper_.Enable(frame_dropping_enabled);
1281 if (frame_dropping_enabled && frame_dropper_.DropFrame()) {
1282 RTC_LOG(LS_VERBOSE)
1283 << "Drop Frame: "
1284 "target bitrate "
1285 << (last_encoder_rate_settings_
1286 ? last_encoder_rate_settings_->encoder_target.bps()
1287 : 0)
1288 << ", input frame rate " << framerate_fps;
1289 OnDroppedFrame(
1290 EncodedImageCallback::DropReason::kDroppedByMediaOptimizations);
1291 accumulated_update_rect_.Union(video_frame.update_rect());
1292 accumulated_update_rect_is_valid_ &= video_frame.has_update_rect();
1293 return;
1294 }
1295
1296 EncodeVideoFrame(video_frame, time_when_posted_us);
1297 }
1298
EncodeVideoFrame(const VideoFrame & video_frame,int64_t time_when_posted_us)1299 void VideoStreamEncoder::EncodeVideoFrame(const VideoFrame& video_frame,
1300 int64_t time_when_posted_us) {
1301 RTC_DCHECK_RUN_ON(&encoder_queue_);
1302
1303 // If the encoder fail we can't continue to encode frames. When this happens
1304 // the WebrtcVideoSender is notified and the whole VideoSendStream is
1305 // recreated.
1306 if (encoder_failed_)
1307 return;
1308
1309 TraceFrameDropEnd();
1310
1311 // Encoder metadata needs to be updated before encode complete callback.
1312 VideoEncoder::EncoderInfo info = encoder_->GetEncoderInfo();
1313 if (info.implementation_name != encoder_info_.implementation_name) {
1314 encoder_stats_observer_->OnEncoderImplementationChanged(
1315 info.implementation_name);
1316 if (bitrate_adjuster_) {
1317 // Encoder implementation changed, reset overshoot detector states.
1318 bitrate_adjuster_->Reset();
1319 }
1320 }
1321
1322 if (encoder_info_ != info) {
1323 OnEncoderSettingsChanged();
1324 RTC_LOG(LS_INFO) << "Encoder settings changed from "
1325 << encoder_info_.ToString() << " to " << info.ToString();
1326 }
1327
1328 if (bitrate_adjuster_) {
1329 for (size_t si = 0; si < kMaxSpatialLayers; ++si) {
1330 if (info.fps_allocation[si] != encoder_info_.fps_allocation[si]) {
1331 bitrate_adjuster_->OnEncoderInfo(info);
1332 break;
1333 }
1334 }
1335 }
1336 encoder_info_ = info;
1337 last_encode_info_ms_ = clock_->TimeInMilliseconds();
1338
1339 VideoFrame out_frame(video_frame);
1340
1341 const VideoFrameBuffer::Type buffer_type =
1342 out_frame.video_frame_buffer()->type();
1343 const bool is_buffer_type_supported =
1344 buffer_type == VideoFrameBuffer::Type::kI420 ||
1345 (buffer_type == VideoFrameBuffer::Type::kNative &&
1346 info.supports_native_handle);
1347
1348 if (!is_buffer_type_supported) {
1349 // This module only supports software encoding.
1350 rtc::scoped_refptr<I420BufferInterface> converted_buffer(
1351 out_frame.video_frame_buffer()->ToI420());
1352
1353 if (!converted_buffer) {
1354 RTC_LOG(LS_ERROR) << "Frame conversion failed, dropping frame.";
1355 return;
1356 }
1357
1358 VideoFrame::UpdateRect update_rect = out_frame.update_rect();
1359 if (!update_rect.IsEmpty() &&
1360 out_frame.video_frame_buffer()->GetI420() == nullptr) {
1361 // UpdatedRect is reset to full update if it's not empty, and buffer was
1362 // converted, therefore we can't guarantee that pixels outside of
1363 // UpdateRect didn't change comparing to the previous frame.
1364 update_rect =
1365 VideoFrame::UpdateRect{0, 0, out_frame.width(), out_frame.height()};
1366 }
1367
1368 out_frame.set_video_frame_buffer(converted_buffer);
1369 out_frame.set_update_rect(update_rect);
1370 }
1371
1372 // Crop frame if needed.
1373 if ((crop_width_ > 0 || crop_height_ > 0) &&
1374 out_frame.video_frame_buffer()->type() !=
1375 VideoFrameBuffer::Type::kNative) {
1376 // If the frame can't be converted to I420, drop it.
1377 auto i420_buffer = video_frame.video_frame_buffer()->ToI420();
1378 if (!i420_buffer) {
1379 RTC_LOG(LS_ERROR) << "Frame conversion for crop failed, dropping frame.";
1380 return;
1381 }
1382 int cropped_width = video_frame.width() - crop_width_;
1383 int cropped_height = video_frame.height() - crop_height_;
1384 rtc::scoped_refptr<I420Buffer> cropped_buffer =
1385 I420Buffer::Create(cropped_width, cropped_height);
1386 // TODO(ilnik): Remove scaling if cropping is too big, as it should never
1387 // happen after SinkWants signaled correctly from ReconfigureEncoder.
1388 VideoFrame::UpdateRect update_rect = video_frame.update_rect();
1389 if (crop_width_ < 4 && crop_height_ < 4) {
1390 cropped_buffer->CropAndScaleFrom(*i420_buffer, crop_width_ / 2,
1391 crop_height_ / 2, cropped_width,
1392 cropped_height);
1393 update_rect.offset_x -= crop_width_ / 2;
1394 update_rect.offset_y -= crop_height_ / 2;
1395 update_rect.Intersect(
1396 VideoFrame::UpdateRect{0, 0, cropped_width, cropped_height});
1397
1398 } else {
1399 cropped_buffer->ScaleFrom(*i420_buffer);
1400 if (!update_rect.IsEmpty()) {
1401 // Since we can't reason about pixels after scaling, we invalidate whole
1402 // picture, if anything changed.
1403 update_rect =
1404 VideoFrame::UpdateRect{0, 0, cropped_width, cropped_height};
1405 }
1406 }
1407 out_frame.set_video_frame_buffer(cropped_buffer);
1408 out_frame.set_update_rect(update_rect);
1409 out_frame.set_ntp_time_ms(video_frame.ntp_time_ms());
1410 // Since accumulated_update_rect_ is constructed before cropping,
1411 // we can't trust it. If any changes were pending, we invalidate whole
1412 // frame here.
1413 if (!accumulated_update_rect_.IsEmpty()) {
1414 accumulated_update_rect_ =
1415 VideoFrame::UpdateRect{0, 0, out_frame.width(), out_frame.height()};
1416 accumulated_update_rect_is_valid_ = false;
1417 }
1418 }
1419
1420 if (!accumulated_update_rect_is_valid_) {
1421 out_frame.clear_update_rect();
1422 } else if (!accumulated_update_rect_.IsEmpty() &&
1423 out_frame.has_update_rect()) {
1424 accumulated_update_rect_.Union(out_frame.update_rect());
1425 accumulated_update_rect_.Intersect(
1426 VideoFrame::UpdateRect{0, 0, out_frame.width(), out_frame.height()});
1427 out_frame.set_update_rect(accumulated_update_rect_);
1428 accumulated_update_rect_.MakeEmptyUpdate();
1429 }
1430 accumulated_update_rect_is_valid_ = true;
1431
1432 TRACE_EVENT_ASYNC_STEP0("webrtc", "Video", video_frame.render_time_ms(),
1433 "Encode");
1434
1435 stream_resource_manager_.OnEncodeStarted(out_frame, time_when_posted_us);
1436
1437 RTC_DCHECK_LE(send_codec_.width, out_frame.width());
1438 RTC_DCHECK_LE(send_codec_.height, out_frame.height());
1439 // Native frames should be scaled by the client.
1440 // For internal encoders we scale everything in one place here.
1441 RTC_DCHECK((out_frame.video_frame_buffer()->type() ==
1442 VideoFrameBuffer::Type::kNative) ||
1443 (send_codec_.width == out_frame.width() &&
1444 send_codec_.height == out_frame.height()));
1445
1446 TRACE_EVENT1("webrtc", "VCMGenericEncoder::Encode", "timestamp",
1447 out_frame.timestamp());
1448
1449 frame_encode_metadata_writer_.OnEncodeStarted(out_frame);
1450
1451 const int32_t encode_status = encoder_->Encode(out_frame, &next_frame_types_);
1452 was_encode_called_since_last_initialization_ = true;
1453
1454 if (encode_status < 0) {
1455 if (encode_status == WEBRTC_VIDEO_CODEC_ENCODER_FAILURE) {
1456 RTC_LOG(LS_ERROR) << "Encoder failed, failing encoder format: "
1457 << encoder_config_.video_format.ToString();
1458
1459 if (settings_.encoder_switch_request_callback) {
1460 if (encoder_selector_) {
1461 if (auto encoder = encoder_selector_->OnEncoderBroken()) {
1462 settings_.encoder_switch_request_callback->RequestEncoderSwitch(
1463 *encoder);
1464 }
1465 } else {
1466 encoder_failed_ = true;
1467 settings_.encoder_switch_request_callback->RequestEncoderFallback();
1468 }
1469 } else {
1470 RTC_LOG(LS_ERROR)
1471 << "Encoder failed but no encoder fallback callback is registered";
1472 }
1473 } else {
1474 RTC_LOG(LS_ERROR) << "Failed to encode frame. Error code: "
1475 << encode_status;
1476 }
1477
1478 return;
1479 }
1480
1481 for (auto& it : next_frame_types_) {
1482 it = VideoFrameType::kVideoFrameDelta;
1483 }
1484 }
1485
SendKeyFrame()1486 void VideoStreamEncoder::SendKeyFrame() {
1487 if (!encoder_queue_.IsCurrent()) {
1488 encoder_queue_.PostTask([this] { SendKeyFrame(); });
1489 return;
1490 }
1491 RTC_DCHECK_RUN_ON(&encoder_queue_);
1492 TRACE_EVENT0("webrtc", "OnKeyFrameRequest");
1493 RTC_DCHECK(!next_frame_types_.empty());
1494
1495 // TODO(webrtc:10615): Map keyframe request to spatial layer.
1496 std::fill(next_frame_types_.begin(), next_frame_types_.end(),
1497 VideoFrameType::kVideoFrameKey);
1498
1499 if (HasInternalSource()) {
1500 // Try to request the frame if we have an external encoder with
1501 // internal source since AddVideoFrame never will be called.
1502
1503 // TODO(nisse): Used only with internal source. Delete as soon as
1504 // that feature is removed. The only implementation I've been able
1505 // to find ignores what's in the frame. With one exception: It seems
1506 // a few test cases, e.g.,
1507 // VideoSendStreamTest.VideoSendStreamStopSetEncoderRateToZero, set
1508 // internal_source to true and use FakeEncoder. And the latter will
1509 // happily encode this 1x1 frame and pass it on down the pipeline.
1510 if (encoder_->Encode(VideoFrame::Builder()
1511 .set_video_frame_buffer(I420Buffer::Create(1, 1))
1512 .set_rotation(kVideoRotation_0)
1513 .set_timestamp_us(0)
1514 .build(),
1515 &next_frame_types_) == WEBRTC_VIDEO_CODEC_OK) {
1516 // Try to remove just-performed keyframe request, if stream still exists.
1517 std::fill(next_frame_types_.begin(), next_frame_types_.end(),
1518 VideoFrameType::kVideoFrameDelta);
1519 }
1520 }
1521 }
1522
OnLossNotification(const VideoEncoder::LossNotification & loss_notification)1523 void VideoStreamEncoder::OnLossNotification(
1524 const VideoEncoder::LossNotification& loss_notification) {
1525 if (!encoder_queue_.IsCurrent()) {
1526 encoder_queue_.PostTask(
1527 [this, loss_notification] { OnLossNotification(loss_notification); });
1528 return;
1529 }
1530
1531 RTC_DCHECK_RUN_ON(&encoder_queue_);
1532 if (encoder_) {
1533 encoder_->OnLossNotification(loss_notification);
1534 }
1535 }
1536
OnEncodedImage(const EncodedImage & encoded_image,const CodecSpecificInfo * codec_specific_info,const RTPFragmentationHeader * fragmentation)1537 EncodedImageCallback::Result VideoStreamEncoder::OnEncodedImage(
1538 const EncodedImage& encoded_image,
1539 const CodecSpecificInfo* codec_specific_info,
1540 const RTPFragmentationHeader* fragmentation) {
1541 TRACE_EVENT_INSTANT1("webrtc", "VCMEncodedFrameCallback::Encoded",
1542 "timestamp", encoded_image.Timestamp());
1543 const size_t spatial_idx = encoded_image.SpatialIndex().value_or(0);
1544 EncodedImage image_copy(encoded_image);
1545
1546 frame_encode_metadata_writer_.FillTimingInfo(spatial_idx, &image_copy);
1547
1548 std::unique_ptr<RTPFragmentationHeader> fragmentation_copy =
1549 frame_encode_metadata_writer_.UpdateBitstream(codec_specific_info,
1550 fragmentation, &image_copy);
1551
1552 // Piggyback ALR experiment group id and simulcast id into the content type.
1553 const uint8_t experiment_id =
1554 experiment_groups_[videocontenttypehelpers::IsScreenshare(
1555 image_copy.content_type_)];
1556
1557 // TODO(ilnik): This will force content type extension to be present even
1558 // for realtime video. At the expense of miniscule overhead we will get
1559 // sliced receive statistics.
1560 RTC_CHECK(videocontenttypehelpers::SetExperimentId(&image_copy.content_type_,
1561 experiment_id));
1562 // We count simulcast streams from 1 on the wire. That's why we set simulcast
1563 // id in content type to +1 of that is actual simulcast index. This is because
1564 // value 0 on the wire is reserved for 'no simulcast stream specified'.
1565 RTC_CHECK(videocontenttypehelpers::SetSimulcastId(
1566 &image_copy.content_type_, static_cast<uint8_t>(spatial_idx + 1)));
1567
1568 // Currently internal quality scaler is used for VP9 instead of webrtc qp
1569 // scaler (in no-svc case or if only a single spatial layer is encoded).
1570 // It has to be explicitly detected and reported to adaptation metrics.
1571 // Post a task because |send_codec_| requires |encoder_queue_| lock.
1572 unsigned int image_width = image_copy._encodedWidth;
1573 unsigned int image_height = image_copy._encodedHeight;
1574 VideoCodecType codec = codec_specific_info
1575 ? codec_specific_info->codecType
1576 : VideoCodecType::kVideoCodecGeneric;
1577 encoder_queue_.PostTask([this, codec, image_width, image_height] {
1578 RTC_DCHECK_RUN_ON(&encoder_queue_);
1579 if (codec == VideoCodecType::kVideoCodecVP9 &&
1580 send_codec_.VP9()->automaticResizeOn) {
1581 unsigned int expected_width = send_codec_.width;
1582 unsigned int expected_height = send_codec_.height;
1583 int num_active_layers = 0;
1584 for (int i = 0; i < send_codec_.VP9()->numberOfSpatialLayers; ++i) {
1585 if (send_codec_.spatialLayers[i].active) {
1586 ++num_active_layers;
1587 expected_width = send_codec_.spatialLayers[i].width;
1588 expected_height = send_codec_.spatialLayers[i].height;
1589 }
1590 }
1591 RTC_DCHECK_LE(num_active_layers, 1)
1592 << "VP9 quality scaling is enabled for "
1593 "SVC with several active layers.";
1594 encoder_stats_observer_->OnEncoderInternalScalerUpdate(
1595 image_width < expected_width || image_height < expected_height);
1596 }
1597 });
1598
1599 // Encoded is called on whatever thread the real encoder implementation run
1600 // on. In the case of hardware encoders, there might be several encoders
1601 // running in parallel on different threads.
1602 encoder_stats_observer_->OnSendEncodedImage(image_copy, codec_specific_info);
1603
1604 // The simulcast id is signaled in the SpatialIndex. This makes it impossible
1605 // to do simulcast for codecs that actually support spatial layers since we
1606 // can't distinguish between an actual spatial layer and a simulcast stream.
1607 // TODO(bugs.webrtc.org/10520): Signal the simulcast id explicitly.
1608 int simulcast_id = 0;
1609 if (codec_specific_info &&
1610 (codec_specific_info->codecType == kVideoCodecVP8 ||
1611 codec_specific_info->codecType == kVideoCodecH264 ||
1612 codec_specific_info->codecType == kVideoCodecGeneric)) {
1613 simulcast_id = encoded_image.SpatialIndex().value_or(0);
1614 }
1615
1616 EncodedImageCallback::Result result = sink_->OnEncodedImage(
1617 image_copy, codec_specific_info,
1618 fragmentation_copy ? fragmentation_copy.get() : fragmentation);
1619
1620 // We are only interested in propagating the meta-data about the image, not
1621 // encoded data itself, to the post encode function. Since we cannot be sure
1622 // the pointer will still be valid when run on the task queue, set it to null.
1623 DataSize frame_size = DataSize::Bytes(image_copy.size());
1624 image_copy.ClearEncodedData();
1625
1626 int temporal_index = 0;
1627 if (codec_specific_info) {
1628 if (codec_specific_info->codecType == kVideoCodecVP9) {
1629 temporal_index = codec_specific_info->codecSpecific.VP9.temporal_idx;
1630 } else if (codec_specific_info->codecType == kVideoCodecVP8) {
1631 temporal_index = codec_specific_info->codecSpecific.VP8.temporalIdx;
1632 }
1633 }
1634 if (temporal_index == kNoTemporalIdx) {
1635 temporal_index = 0;
1636 }
1637
1638 RunPostEncode(image_copy, rtc::TimeMicros(), temporal_index, frame_size);
1639
1640 if (result.error == Result::OK) {
1641 // In case of an internal encoder running on a separate thread, the
1642 // decision to drop a frame might be a frame late and signaled via
1643 // atomic flag. This is because we can't easily wait for the worker thread
1644 // without risking deadlocks, eg during shutdown when the worker thread
1645 // might be waiting for the internal encoder threads to stop.
1646 if (pending_frame_drops_.load() > 0) {
1647 int pending_drops = pending_frame_drops_.fetch_sub(1);
1648 RTC_DCHECK_GT(pending_drops, 0);
1649 result.drop_next_frame = true;
1650 }
1651 }
1652
1653 return result;
1654 }
1655
OnDroppedFrame(DropReason reason)1656 void VideoStreamEncoder::OnDroppedFrame(DropReason reason) {
1657 switch (reason) {
1658 case DropReason::kDroppedByMediaOptimizations:
1659 encoder_stats_observer_->OnFrameDropped(
1660 VideoStreamEncoderObserver::DropReason::kMediaOptimization);
1661 break;
1662 case DropReason::kDroppedByEncoder:
1663 encoder_stats_observer_->OnFrameDropped(
1664 VideoStreamEncoderObserver::DropReason::kEncoder);
1665 break;
1666 }
1667 sink_->OnDroppedFrame(reason);
1668 encoder_queue_.PostTask([this, reason] {
1669 RTC_DCHECK_RUN_ON(&encoder_queue_);
1670 stream_resource_manager_.OnFrameDropped(reason);
1671 });
1672 }
1673
UpdateTargetBitrate(DataRate target_bitrate,double cwnd_reduce_ratio)1674 DataRate VideoStreamEncoder::UpdateTargetBitrate(DataRate target_bitrate,
1675 double cwnd_reduce_ratio) {
1676 RTC_DCHECK_RUN_ON(&encoder_queue_);
1677 DataRate updated_target_bitrate = target_bitrate;
1678
1679 // Drop frames when congestion window pushback ratio is larger than 1
1680 // percent and target bitrate is larger than codec min bitrate.
1681 // When target_bitrate is 0 means codec is paused, skip frame dropping.
1682 if (cwnd_reduce_ratio > 0.01 && target_bitrate.bps() > 0 &&
1683 target_bitrate.bps() > send_codec_.minBitrate * 1000) {
1684 int reduce_bitrate_bps = std::min(
1685 static_cast<int>(target_bitrate.bps() * cwnd_reduce_ratio),
1686 static_cast<int>(target_bitrate.bps() - send_codec_.minBitrate * 1000));
1687 if (reduce_bitrate_bps > 0) {
1688 // At maximum the congestion window can drop 1/2 frames.
1689 cwnd_frame_drop_interval_ = std::max(
1690 2, static_cast<int>(target_bitrate.bps() / reduce_bitrate_bps));
1691 // Reduce target bitrate accordingly.
1692 updated_target_bitrate =
1693 target_bitrate - (target_bitrate / cwnd_frame_drop_interval_.value());
1694 return updated_target_bitrate;
1695 }
1696 }
1697 cwnd_frame_drop_interval_.reset();
1698 return updated_target_bitrate;
1699 }
1700
OnBitrateUpdated(DataRate target_bitrate,DataRate stable_target_bitrate,DataRate link_allocation,uint8_t fraction_lost,int64_t round_trip_time_ms,double cwnd_reduce_ratio)1701 void VideoStreamEncoder::OnBitrateUpdated(DataRate target_bitrate,
1702 DataRate stable_target_bitrate,
1703 DataRate link_allocation,
1704 uint8_t fraction_lost,
1705 int64_t round_trip_time_ms,
1706 double cwnd_reduce_ratio) {
1707 RTC_DCHECK_GE(link_allocation, target_bitrate);
1708 if (!encoder_queue_.IsCurrent()) {
1709 encoder_queue_.PostTask([this, target_bitrate, stable_target_bitrate,
1710 link_allocation, fraction_lost, round_trip_time_ms,
1711 cwnd_reduce_ratio] {
1712 DataRate updated_target_bitrate =
1713 UpdateTargetBitrate(target_bitrate, cwnd_reduce_ratio);
1714 OnBitrateUpdated(updated_target_bitrate, stable_target_bitrate,
1715 link_allocation, fraction_lost, round_trip_time_ms,
1716 cwnd_reduce_ratio);
1717 });
1718 return;
1719 }
1720 RTC_DCHECK_RUN_ON(&encoder_queue_);
1721
1722 const bool video_is_suspended = target_bitrate == DataRate::Zero();
1723 const bool video_suspension_changed = video_is_suspended != EncoderPaused();
1724
1725 if (!video_is_suspended && settings_.encoder_switch_request_callback) {
1726 if (encoder_selector_) {
1727 if (auto encoder =
1728 encoder_selector_->OnAvailableBitrate(link_allocation)) {
1729 settings_.encoder_switch_request_callback->RequestEncoderSwitch(
1730 *encoder);
1731 }
1732 } else if (encoder_switch_experiment_.IsBitrateBelowThreshold(
1733 target_bitrate) &&
1734 !encoder_switch_requested_) {
1735 EncoderSwitchRequestCallback::Config conf;
1736 conf.codec_name = encoder_switch_experiment_.to_codec;
1737 conf.param = encoder_switch_experiment_.to_param;
1738 conf.value = encoder_switch_experiment_.to_value;
1739 settings_.encoder_switch_request_callback->RequestEncoderSwitch(conf);
1740
1741 encoder_switch_requested_ = true;
1742 }
1743 }
1744
1745 RTC_DCHECK(sink_) << "sink_ must be set before the encoder is active.";
1746
1747 RTC_LOG(LS_VERBOSE) << "OnBitrateUpdated, bitrate " << target_bitrate.bps()
1748 << " stable bitrate = " << stable_target_bitrate.bps()
1749 << " link allocation bitrate = " << link_allocation.bps()
1750 << " packet loss " << static_cast<int>(fraction_lost)
1751 << " rtt " << round_trip_time_ms;
1752
1753 if (encoder_) {
1754 encoder_->OnPacketLossRateUpdate(static_cast<float>(fraction_lost) / 256.f);
1755 encoder_->OnRttUpdate(round_trip_time_ms);
1756 }
1757
1758 uint32_t framerate_fps = GetInputFramerateFps();
1759 frame_dropper_.SetRates((target_bitrate.bps() + 500) / 1000, framerate_fps);
1760
1761 EncoderRateSettings new_rate_settings{
1762 VideoBitrateAllocation(), static_cast<double>(framerate_fps),
1763 link_allocation, target_bitrate, stable_target_bitrate};
1764 SetEncoderRates(UpdateBitrateAllocationAndNotifyObserver(new_rate_settings));
1765
1766 if (target_bitrate.bps() != 0)
1767 encoder_target_bitrate_bps_ = target_bitrate.bps();
1768
1769 stream_resource_manager_.SetTargetBitrate(target_bitrate);
1770
1771 if (video_suspension_changed) {
1772 RTC_LOG(LS_INFO) << "Video suspend state changed to: "
1773 << (video_is_suspended ? "suspended" : "not suspended");
1774 encoder_stats_observer_->OnSuspendChange(video_is_suspended);
1775 }
1776 if (video_suspension_changed && !video_is_suspended && pending_frame_ &&
1777 !DropDueToSize(pending_frame_->size())) {
1778 int64_t pending_time_us = rtc::TimeMicros() - pending_frame_post_time_us_;
1779 if (pending_time_us < kPendingFrameTimeoutMs * 1000)
1780 EncodeVideoFrame(*pending_frame_, pending_frame_post_time_us_);
1781 pending_frame_.reset();
1782 }
1783 }
1784
DropDueToSize(uint32_t pixel_count) const1785 bool VideoStreamEncoder::DropDueToSize(uint32_t pixel_count) const {
1786 bool simulcast_or_svc =
1787 (send_codec_.codecType == VideoCodecType::kVideoCodecVP9 &&
1788 send_codec_.VP9().numberOfSpatialLayers > 1) ||
1789 send_codec_.numberOfSimulcastStreams > 1 ||
1790 encoder_config_.simulcast_layers.size() > 1;
1791
1792 if (simulcast_or_svc || !stream_resource_manager_.DropInitialFrames() ||
1793 !encoder_target_bitrate_bps_.has_value()) {
1794 return false;
1795 }
1796
1797 absl::optional<VideoEncoder::ResolutionBitrateLimits> encoder_bitrate_limits =
1798 encoder_->GetEncoderInfo().GetEncoderBitrateLimitsForResolution(
1799 pixel_count);
1800
1801 if (encoder_bitrate_limits.has_value()) {
1802 // Use bitrate limits provided by encoder.
1803 return encoder_target_bitrate_bps_.value() <
1804 static_cast<uint32_t>(encoder_bitrate_limits->min_start_bitrate_bps);
1805 }
1806
1807 if (encoder_target_bitrate_bps_.value() < 300000 /* qvga */) {
1808 return pixel_count > 320 * 240;
1809 } else if (encoder_target_bitrate_bps_.value() < 500000 /* vga */) {
1810 return pixel_count > 640 * 480;
1811 }
1812 return false;
1813 }
1814
OnVideoSourceRestrictionsUpdated(VideoSourceRestrictions restrictions,const VideoAdaptationCounters & adaptation_counters,rtc::scoped_refptr<Resource> reason,const VideoSourceRestrictions & unfiltered_restrictions)1815 void VideoStreamEncoder::OnVideoSourceRestrictionsUpdated(
1816 VideoSourceRestrictions restrictions,
1817 const VideoAdaptationCounters& adaptation_counters,
1818 rtc::scoped_refptr<Resource> reason,
1819 const VideoSourceRestrictions& unfiltered_restrictions) {
1820 RTC_DCHECK_RUN_ON(&resource_adaptation_queue_);
1821 std::string resource_name = reason ? reason->Name() : "<null>";
1822 RTC_LOG(INFO) << "Updating sink restrictions from " << resource_name << " to "
1823 << restrictions.ToString();
1824 video_source_sink_controller_.SetRestrictions(std::move(restrictions));
1825 video_source_sink_controller_.PushSourceSinkSettings();
1826 }
1827
RunPostEncode(const EncodedImage & encoded_image,int64_t time_sent_us,int temporal_index,DataSize frame_size)1828 void VideoStreamEncoder::RunPostEncode(const EncodedImage& encoded_image,
1829 int64_t time_sent_us,
1830 int temporal_index,
1831 DataSize frame_size) {
1832 if (!encoder_queue_.IsCurrent()) {
1833 encoder_queue_.PostTask([this, encoded_image, time_sent_us, temporal_index,
1834 frame_size] {
1835 RunPostEncode(encoded_image, time_sent_us, temporal_index, frame_size);
1836 });
1837 return;
1838 }
1839
1840 RTC_DCHECK_RUN_ON(&encoder_queue_);
1841
1842 absl::optional<int> encode_duration_us;
1843 if (encoded_image.timing_.flags != VideoSendTiming::kInvalid) {
1844 encode_duration_us =
1845 // TODO(nisse): Maybe use capture_time_ms_ rather than encode_start_ms_?
1846 rtc::kNumMicrosecsPerMillisec *
1847 (encoded_image.timing_.encode_finish_ms -
1848 encoded_image.timing_.encode_start_ms);
1849 }
1850
1851 // Run post encode tasks, such as overuse detection and frame rate/drop
1852 // stats for internal encoders.
1853 const bool keyframe =
1854 encoded_image._frameType == VideoFrameType::kVideoFrameKey;
1855
1856 if (!frame_size.IsZero()) {
1857 frame_dropper_.Fill(frame_size.bytes(), !keyframe);
1858 }
1859
1860 if (HasInternalSource()) {
1861 // Update frame dropper after the fact for internal sources.
1862 input_framerate_.Update(1u, clock_->TimeInMilliseconds());
1863 frame_dropper_.Leak(GetInputFramerateFps());
1864 // Signal to encoder to drop next frame.
1865 if (frame_dropper_.DropFrame()) {
1866 pending_frame_drops_.fetch_add(1);
1867 }
1868 }
1869
1870 stream_resource_manager_.OnEncodeCompleted(encoded_image, time_sent_us,
1871 encode_duration_us);
1872 if (bitrate_adjuster_) {
1873 bitrate_adjuster_->OnEncodedFrame(encoded_image, temporal_index);
1874 }
1875 }
1876
HasInternalSource() const1877 bool VideoStreamEncoder::HasInternalSource() const {
1878 // TODO(sprang): Checking both info from encoder and from encoder factory
1879 // until we have deprecated and removed the encoder factory info.
1880 return codec_info_.has_internal_source || encoder_info_.has_internal_source;
1881 }
1882
ReleaseEncoder()1883 void VideoStreamEncoder::ReleaseEncoder() {
1884 if (!encoder_ || !encoder_initialized_) {
1885 return;
1886 }
1887 encoder_->Release();
1888 encoder_initialized_ = false;
1889 TRACE_EVENT0("webrtc", "VCMGenericEncoder::Release");
1890 }
1891
IsBitrateBelowThreshold(const DataRate & target_bitrate)1892 bool VideoStreamEncoder::EncoderSwitchExperiment::IsBitrateBelowThreshold(
1893 const DataRate& target_bitrate) {
1894 DataRate rate = DataRate::KilobitsPerSec(
1895 bitrate_filter.Apply(1.0, target_bitrate.kbps()));
1896 return current_thresholds.bitrate && rate < *current_thresholds.bitrate;
1897 }
1898
IsPixelCountBelowThreshold(int pixel_count) const1899 bool VideoStreamEncoder::EncoderSwitchExperiment::IsPixelCountBelowThreshold(
1900 int pixel_count) const {
1901 return current_thresholds.pixel_count &&
1902 pixel_count < *current_thresholds.pixel_count;
1903 }
1904
SetCodec(VideoCodecType codec)1905 void VideoStreamEncoder::EncoderSwitchExperiment::SetCodec(
1906 VideoCodecType codec) {
1907 auto it = codec_thresholds.find(codec);
1908 if (it == codec_thresholds.end()) {
1909 current_thresholds = {};
1910 } else {
1911 current_thresholds = it->second;
1912 }
1913 }
1914
1915 VideoStreamEncoder::EncoderSwitchExperiment
ParseEncoderSwitchFieldTrial() const1916 VideoStreamEncoder::ParseEncoderSwitchFieldTrial() const {
1917 EncoderSwitchExperiment result;
1918
1919 // Each "codec threshold" have the format
1920 // "<codec name>;<bitrate kbps>;<pixel count>", and are separated by the "|"
1921 // character.
1922 webrtc::FieldTrialOptional<std::string> codec_thresholds_string{
1923 "codec_thresholds"};
1924 webrtc::FieldTrialOptional<std::string> to_codec{"to_codec"};
1925 webrtc::FieldTrialOptional<std::string> to_param{"to_param"};
1926 webrtc::FieldTrialOptional<std::string> to_value{"to_value"};
1927 webrtc::FieldTrialOptional<double> window{"window"};
1928
1929 webrtc::ParseFieldTrial(
1930 {&codec_thresholds_string, &to_codec, &to_param, &to_value, &window},
1931 webrtc::field_trial::FindFullName(
1932 "WebRTC-NetworkCondition-EncoderSwitch"));
1933
1934 if (!codec_thresholds_string || !to_codec || !window) {
1935 return {};
1936 }
1937
1938 result.bitrate_filter.Reset(1.0 - 1.0 / *window);
1939 result.to_codec = *to_codec;
1940 result.to_param = to_param.GetOptional();
1941 result.to_value = to_value.GetOptional();
1942
1943 std::vector<std::string> codecs_thresholds;
1944 if (rtc::split(*codec_thresholds_string, '|', &codecs_thresholds) == 0) {
1945 return {};
1946 }
1947
1948 for (const std::string& codec_threshold : codecs_thresholds) {
1949 std::vector<std::string> thresholds_split;
1950 if (rtc::split(codec_threshold, ';', &thresholds_split) != 3) {
1951 return {};
1952 }
1953
1954 VideoCodecType codec = PayloadStringToCodecType(thresholds_split[0]);
1955 int bitrate_kbps;
1956 rtc::FromString(thresholds_split[1], &bitrate_kbps);
1957 int pixel_count;
1958 rtc::FromString(thresholds_split[2], &pixel_count);
1959
1960 if (bitrate_kbps > 0) {
1961 result.codec_thresholds[codec].bitrate =
1962 DataRate::KilobitsPerSec(bitrate_kbps);
1963 }
1964
1965 if (pixel_count > 0) {
1966 result.codec_thresholds[codec].pixel_count = pixel_count;
1967 }
1968
1969 if (!result.codec_thresholds[codec].bitrate &&
1970 !result.codec_thresholds[codec].pixel_count) {
1971 return {};
1972 }
1973 }
1974
1975 rtc::StringBuilder ss;
1976 ss << "Successfully parsed WebRTC-NetworkCondition-EncoderSwitch field "
1977 "trial."
1978 " to_codec:"
1979 << result.to_codec << " to_param:" << result.to_param.value_or("<none>")
1980 << " to_value:" << result.to_value.value_or("<none>")
1981 << " codec_thresholds:";
1982
1983 for (auto kv : result.codec_thresholds) {
1984 std::string codec_name = CodecTypeToPayloadString(kv.first);
1985 std::string bitrate = kv.second.bitrate
1986 ? std::to_string(kv.second.bitrate->kbps())
1987 : "<none>";
1988 std::string pixels = kv.second.pixel_count
1989 ? std::to_string(*kv.second.pixel_count)
1990 : "<none>";
1991 ss << " (" << codec_name << ":" << bitrate << ":" << pixels << ")";
1992 }
1993
1994 RTC_LOG(LS_INFO) << ss.str();
1995
1996 return result;
1997 }
1998
1999 VideoStreamEncoder::AutomaticAnimationDetectionExperiment
ParseAutomatincAnimationDetectionFieldTrial() const2000 VideoStreamEncoder::ParseAutomatincAnimationDetectionFieldTrial() const {
2001 AutomaticAnimationDetectionExperiment result;
2002
2003 result.Parser()->Parse(webrtc::field_trial::FindFullName(
2004 "WebRTC-AutomaticAnimationDetectionScreenshare"));
2005
2006 if (!result.enabled) {
2007 RTC_LOG(LS_INFO) << "Automatic animation detection experiment is disabled.";
2008 return result;
2009 }
2010
2011 RTC_LOG(LS_INFO) << "Automatic animation detection experiment settings:"
2012 " min_duration_ms="
2013 << result.min_duration_ms
2014 << " min_area_ration=" << result.min_area_ratio
2015 << " min_fps=" << result.min_fps;
2016
2017 return result;
2018 }
2019
CheckForAnimatedContent(const VideoFrame & frame,int64_t time_when_posted_in_us)2020 void VideoStreamEncoder::CheckForAnimatedContent(
2021 const VideoFrame& frame,
2022 int64_t time_when_posted_in_us) {
2023 if (!automatic_animation_detection_experiment_.enabled ||
2024 encoder_config_.content_type !=
2025 VideoEncoderConfig::ContentType::kScreen ||
2026 stream_resource_manager_.degradation_preference() !=
2027 DegradationPreference::BALANCED) {
2028 return;
2029 }
2030
2031 if (expect_resize_state_ == ExpectResizeState::kResize && last_frame_info_ &&
2032 last_frame_info_->width != frame.width() &&
2033 last_frame_info_->height != frame.height()) {
2034 // On applying resolution cap there will be one frame with no/different
2035 // update, which should be skipped.
2036 // It can be delayed by several frames.
2037 expect_resize_state_ = ExpectResizeState::kFirstFrameAfterResize;
2038 return;
2039 }
2040
2041 if (expect_resize_state_ == ExpectResizeState::kFirstFrameAfterResize) {
2042 // The first frame after resize should have new, scaled update_rect.
2043 if (frame.has_update_rect()) {
2044 last_update_rect_ = frame.update_rect();
2045 } else {
2046 last_update_rect_ = absl::nullopt;
2047 }
2048 expect_resize_state_ = ExpectResizeState::kNoResize;
2049 }
2050
2051 bool should_cap_resolution = false;
2052 if (!frame.has_update_rect()) {
2053 last_update_rect_ = absl::nullopt;
2054 animation_start_time_ = Timestamp::PlusInfinity();
2055 } else if ((!last_update_rect_ ||
2056 frame.update_rect() != *last_update_rect_)) {
2057 last_update_rect_ = frame.update_rect();
2058 animation_start_time_ = Timestamp::Micros(time_when_posted_in_us);
2059 } else {
2060 TimeDelta animation_duration =
2061 Timestamp::Micros(time_when_posted_in_us) - animation_start_time_;
2062 float area_ratio = static_cast<float>(last_update_rect_->width *
2063 last_update_rect_->height) /
2064 (frame.width() * frame.height());
2065 if (animation_duration.ms() >=
2066 automatic_animation_detection_experiment_.min_duration_ms &&
2067 area_ratio >=
2068 automatic_animation_detection_experiment_.min_area_ratio &&
2069 encoder_stats_observer_->GetInputFrameRate() >=
2070 automatic_animation_detection_experiment_.min_fps) {
2071 should_cap_resolution = true;
2072 }
2073 }
2074 if (cap_resolution_due_to_video_content_ != should_cap_resolution) {
2075 expect_resize_state_ = should_cap_resolution ? ExpectResizeState::kResize
2076 : ExpectResizeState::kNoResize;
2077 cap_resolution_due_to_video_content_ = should_cap_resolution;
2078 if (should_cap_resolution) {
2079 RTC_LOG(LS_INFO) << "Applying resolution cap due to animation detection.";
2080 } else {
2081 RTC_LOG(LS_INFO) << "Removing resolution cap due to no consistent "
2082 "animation detection.";
2083 }
2084 video_source_sink_controller_.SetPixelsPerFrameUpperLimit(
2085 should_cap_resolution ? absl::optional<size_t>(kMaxAnimationPixels)
2086 : absl::nullopt);
2087 video_source_sink_controller_.PushSourceSinkSettings();
2088 }
2089 }
InjectAdaptationResource(rtc::scoped_refptr<Resource> resource,VideoAdaptationReason reason)2090 void VideoStreamEncoder::InjectAdaptationResource(
2091 rtc::scoped_refptr<Resource> resource,
2092 VideoAdaptationReason reason) {
2093 rtc::Event map_resource_event;
2094 encoder_queue_.PostTask([this, resource, reason, &map_resource_event] {
2095 RTC_DCHECK_RUN_ON(&encoder_queue_);
2096 stream_resource_manager_.MapResourceToReason(resource, reason);
2097 resource_adaptation_processor_->AddResource(resource);
2098 map_resource_event.Set();
2099 });
2100 map_resource_event.Wait(rtc::Event::kForever);
2101 }
2102
InjectAdaptationConstraint(AdaptationConstraint * adaptation_constraint)2103 void VideoStreamEncoder::InjectAdaptationConstraint(
2104 AdaptationConstraint* adaptation_constraint) {
2105 rtc::Event event;
2106 resource_adaptation_queue_.PostTask([this, adaptation_constraint, &event] {
2107 RTC_DCHECK_RUN_ON(&resource_adaptation_queue_);
2108 if (!resource_adaptation_processor_) {
2109 // The VideoStreamEncoder was stopped and the processor destroyed before
2110 // this task had a chance to execute. No action needed.
2111 return;
2112 }
2113 adaptation_constraints_.push_back(adaptation_constraint);
2114 video_stream_adapter_->AddAdaptationConstraint(adaptation_constraint);
2115 event.Set();
2116 });
2117 event.Wait(rtc::Event::kForever);
2118 }
2119
2120 rtc::scoped_refptr<QualityScalerResource>
quality_scaler_resource_for_testing()2121 VideoStreamEncoder::quality_scaler_resource_for_testing() {
2122 RTC_DCHECK_RUN_ON(&encoder_queue_);
2123 return stream_resource_manager_.quality_scaler_resource_for_testing();
2124 }
2125
AddRestrictionsListenerForTesting(VideoSourceRestrictionsListener * restrictions_listener)2126 void VideoStreamEncoder::AddRestrictionsListenerForTesting(
2127 VideoSourceRestrictionsListener* restrictions_listener) {
2128 rtc::Event event;
2129 resource_adaptation_queue_.PostTask([this, restrictions_listener, &event] {
2130 RTC_DCHECK_RUN_ON(&resource_adaptation_queue_);
2131 RTC_DCHECK(resource_adaptation_processor_);
2132 video_stream_adapter_->AddRestrictionsListener(restrictions_listener);
2133 event.Set();
2134 });
2135 event.Wait(rtc::Event::kForever);
2136 }
2137
RemoveRestrictionsListenerForTesting(VideoSourceRestrictionsListener * restrictions_listener)2138 void VideoStreamEncoder::RemoveRestrictionsListenerForTesting(
2139 VideoSourceRestrictionsListener* restrictions_listener) {
2140 rtc::Event event;
2141 resource_adaptation_queue_.PostTask([this, restrictions_listener, &event] {
2142 RTC_DCHECK_RUN_ON(&resource_adaptation_queue_);
2143 RTC_DCHECK(resource_adaptation_processor_);
2144 video_stream_adapter_->RemoveRestrictionsListener(restrictions_listener);
2145 event.Set();
2146 });
2147 event.Wait(rtc::Event::kForever);
2148 }
2149
2150 } // namespace webrtc
2151