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/cleanup/cleanup.h"
22 #include "absl/types/optional.h"
23 #include "api/field_trials_view.h"
24 #include "api/sequence_checker.h"
25 #include "api/task_queue/task_queue_base.h"
26 #include "api/video/encoded_image.h"
27 #include "api/video/i420_buffer.h"
28 #include "api/video/render_resolution.h"
29 #include "api/video/video_adaptation_reason.h"
30 #include "api/video/video_bitrate_allocator_factory.h"
31 #include "api/video/video_codec_constants.h"
32 #include "api/video/video_layers_allocation.h"
33 #include "api/video_codecs/sdp_video_format.h"
34 #include "api/video_codecs/video_encoder.h"
35 #include "call/adaptation/resource_adaptation_processor.h"
36 #include "call/adaptation/video_source_restrictions.h"
37 #include "call/adaptation/video_stream_adapter.h"
38 #include "media/base/media_channel.h"
39 #include "modules/video_coding/include/video_codec_initializer.h"
40 #include "modules/video_coding/svc/svc_rate_allocator.h"
41 #include "modules/video_coding/utility/vp8_constants.h"
42 #include "rtc_base/arraysize.h"
43 #include "rtc_base/checks.h"
44 #include "rtc_base/event.h"
45 #include "rtc_base/experiments/alr_experiment.h"
46 #include "rtc_base/experiments/encoder_info_settings.h"
47 #include "rtc_base/experiments/rate_control_settings.h"
48 #include "rtc_base/logging.h"
49 #include "rtc_base/strings/string_builder.h"
50 #include "rtc_base/system/no_unique_address.h"
51 #include "rtc_base/thread_annotations.h"
52 #include "rtc_base/trace_event.h"
53 #include "system_wrappers/include/metrics.h"
54 #include "video/adaptation/video_stream_encoder_resource_manager.h"
55 #include "video/alignment_adjuster.h"
56 #include "video/config/encoder_stream_factory.h"
57 #include "video/frame_cadence_adapter.h"
58
59 namespace webrtc {
60
61 namespace {
62
63 // Time interval for logging frame counts.
64 const int64_t kFrameLogIntervalMs = 60000;
65
66 // Time to keep a single cached pending frame in paused state.
67 const int64_t kPendingFrameTimeoutMs = 1000;
68
69 constexpr char kFrameDropperFieldTrial[] = "WebRTC-FrameDropper";
70
71 // TODO(bugs.webrtc.org/13572): Remove this kill switch after deploying the
72 // feature.
73 constexpr char kSwitchEncoderOnInitializationFailuresFieldTrial[] =
74 "WebRTC-SwitchEncoderOnInitializationFailures";
75
76 const size_t kDefaultPayloadSize = 1440;
77
78 const int64_t kParameterUpdateIntervalMs = 1000;
79
80 // Animation is capped to 720p.
81 constexpr int kMaxAnimationPixels = 1280 * 720;
82
83 constexpr int kDefaultMinScreenSharebps = 1200000;
84
RequiresEncoderReset(const VideoCodec & prev_send_codec,const VideoCodec & new_send_codec,bool was_encode_called_since_last_initialization)85 bool RequiresEncoderReset(const VideoCodec& prev_send_codec,
86 const VideoCodec& new_send_codec,
87 bool was_encode_called_since_last_initialization) {
88 // Does not check max/minBitrate or maxFramerate.
89 if (new_send_codec.codecType != prev_send_codec.codecType ||
90 new_send_codec.width != prev_send_codec.width ||
91 new_send_codec.height != prev_send_codec.height ||
92 new_send_codec.qpMax != prev_send_codec.qpMax ||
93 new_send_codec.numberOfSimulcastStreams !=
94 prev_send_codec.numberOfSimulcastStreams ||
95 new_send_codec.mode != prev_send_codec.mode ||
96 new_send_codec.GetFrameDropEnabled() !=
97 prev_send_codec.GetFrameDropEnabled()) {
98 return true;
99 }
100
101 if (!was_encode_called_since_last_initialization &&
102 (new_send_codec.startBitrate != prev_send_codec.startBitrate)) {
103 // If start bitrate has changed reconfigure encoder only if encoding had not
104 // yet started.
105 return true;
106 }
107
108 switch (new_send_codec.codecType) {
109 case kVideoCodecVP8:
110 if (new_send_codec.VP8() != prev_send_codec.VP8()) {
111 return true;
112 }
113 break;
114
115 case kVideoCodecVP9:
116 if (new_send_codec.VP9() != prev_send_codec.VP9()) {
117 return true;
118 }
119 break;
120
121 case kVideoCodecH264:
122 if (new_send_codec.H264() != prev_send_codec.H264()) {
123 return true;
124 }
125 break;
126
127 default:
128 break;
129 }
130
131 for (unsigned char i = 0; i < new_send_codec.numberOfSimulcastStreams; ++i) {
132 if (!new_send_codec.simulcastStream[i].active) {
133 // No need to reset when stream is inactive.
134 continue;
135 }
136
137 if (!prev_send_codec.simulcastStream[i].active ||
138 new_send_codec.simulcastStream[i].width !=
139 prev_send_codec.simulcastStream[i].width ||
140 new_send_codec.simulcastStream[i].height !=
141 prev_send_codec.simulcastStream[i].height ||
142 new_send_codec.simulcastStream[i].numberOfTemporalLayers !=
143 prev_send_codec.simulcastStream[i].numberOfTemporalLayers ||
144 new_send_codec.simulcastStream[i].qpMax !=
145 prev_send_codec.simulcastStream[i].qpMax) {
146 return true;
147 }
148 }
149
150 if (new_send_codec.codecType == kVideoCodecVP9) {
151 size_t num_spatial_layers = new_send_codec.VP9().numberOfSpatialLayers;
152 for (unsigned char i = 0; i < num_spatial_layers; ++i) {
153 if (new_send_codec.spatialLayers[i].width !=
154 prev_send_codec.spatialLayers[i].width ||
155 new_send_codec.spatialLayers[i].height !=
156 prev_send_codec.spatialLayers[i].height ||
157 new_send_codec.spatialLayers[i].numberOfTemporalLayers !=
158 prev_send_codec.spatialLayers[i].numberOfTemporalLayers ||
159 new_send_codec.spatialLayers[i].qpMax !=
160 prev_send_codec.spatialLayers[i].qpMax) {
161 return true;
162 }
163 }
164 }
165
166 if (new_send_codec.GetScalabilityMode() !=
167 prev_send_codec.GetScalabilityMode()) {
168 return true;
169 }
170
171 return false;
172 }
173
GetExperimentGroups()174 std::array<uint8_t, 2> GetExperimentGroups() {
175 std::array<uint8_t, 2> experiment_groups;
176 absl::optional<AlrExperimentSettings> experiment_settings =
177 AlrExperimentSettings::CreateFromFieldTrial(
178 AlrExperimentSettings::kStrictPacingAndProbingExperimentName);
179 if (experiment_settings) {
180 experiment_groups[0] = experiment_settings->group_id + 1;
181 } else {
182 experiment_groups[0] = 0;
183 }
184 experiment_settings = AlrExperimentSettings::CreateFromFieldTrial(
185 AlrExperimentSettings::kScreenshareProbingBweExperimentName);
186 if (experiment_settings) {
187 experiment_groups[1] = experiment_settings->group_id + 1;
188 } else {
189 experiment_groups[1] = 0;
190 }
191 return experiment_groups;
192 }
193
194 // Limit allocation across TLs in bitrate allocation according to number of TLs
195 // in EncoderInfo.
UpdateAllocationFromEncoderInfo(const VideoBitrateAllocation & allocation,const VideoEncoder::EncoderInfo & encoder_info)196 VideoBitrateAllocation UpdateAllocationFromEncoderInfo(
197 const VideoBitrateAllocation& allocation,
198 const VideoEncoder::EncoderInfo& encoder_info) {
199 if (allocation.get_sum_bps() == 0) {
200 return allocation;
201 }
202 VideoBitrateAllocation new_allocation;
203 for (int si = 0; si < kMaxSpatialLayers; ++si) {
204 if (encoder_info.fps_allocation[si].size() == 1 &&
205 allocation.IsSpatialLayerUsed(si)) {
206 // One TL is signalled to be used by the encoder. Do not distribute
207 // bitrate allocation across TLs (use sum at ti:0).
208 new_allocation.SetBitrate(si, 0, allocation.GetSpatialLayerSum(si));
209 } else {
210 for (int ti = 0; ti < kMaxTemporalStreams; ++ti) {
211 if (allocation.HasBitrate(si, ti))
212 new_allocation.SetBitrate(si, ti, allocation.GetBitrate(si, ti));
213 }
214 }
215 }
216 new_allocation.set_bw_limited(allocation.is_bw_limited());
217 return new_allocation;
218 }
219
220 // Converts a VideoBitrateAllocation that contains allocated bitrate per layer,
221 // and an EncoderInfo that contains information about the actual encoder
222 // structure used by a codec. Stream structures can be Ksvc, Full SVC, Simulcast
223 // etc.
CreateVideoLayersAllocation(const VideoCodec & encoder_config,const VideoEncoder::RateControlParameters & current_rate,const VideoEncoder::EncoderInfo & encoder_info)224 VideoLayersAllocation CreateVideoLayersAllocation(
225 const VideoCodec& encoder_config,
226 const VideoEncoder::RateControlParameters& current_rate,
227 const VideoEncoder::EncoderInfo& encoder_info) {
228 const VideoBitrateAllocation& target_bitrate = current_rate.target_bitrate;
229 VideoLayersAllocation layers_allocation;
230 if (target_bitrate.get_sum_bps() == 0) {
231 return layers_allocation;
232 }
233
234 if (encoder_config.numberOfSimulcastStreams > 1) {
235 layers_allocation.resolution_and_frame_rate_is_valid = true;
236 for (int si = 0; si < encoder_config.numberOfSimulcastStreams; ++si) {
237 if (!target_bitrate.IsSpatialLayerUsed(si) ||
238 target_bitrate.GetSpatialLayerSum(si) == 0) {
239 continue;
240 }
241 layers_allocation.active_spatial_layers.emplace_back();
242 VideoLayersAllocation::SpatialLayer& spatial_layer =
243 layers_allocation.active_spatial_layers.back();
244 spatial_layer.width = encoder_config.simulcastStream[si].width;
245 spatial_layer.height = encoder_config.simulcastStream[si].height;
246 spatial_layer.rtp_stream_index = si;
247 spatial_layer.spatial_id = 0;
248 auto frame_rate_fraction =
249 VideoEncoder::EncoderInfo::kMaxFramerateFraction;
250 if (encoder_info.fps_allocation[si].size() == 1) {
251 // One TL is signalled to be used by the encoder. Do not distribute
252 // bitrate allocation across TLs (use sum at tl:0).
253 spatial_layer.target_bitrate_per_temporal_layer.push_back(
254 DataRate::BitsPerSec(target_bitrate.GetSpatialLayerSum(si)));
255 frame_rate_fraction = encoder_info.fps_allocation[si][0];
256 } else { // Temporal layers are supported.
257 uint32_t temporal_layer_bitrate_bps = 0;
258 for (size_t ti = 0;
259 ti < encoder_config.simulcastStream[si].numberOfTemporalLayers;
260 ++ti) {
261 if (!target_bitrate.HasBitrate(si, ti)) {
262 break;
263 }
264 if (ti < encoder_info.fps_allocation[si].size()) {
265 // Use frame rate of the top used temporal layer.
266 frame_rate_fraction = encoder_info.fps_allocation[si][ti];
267 }
268 temporal_layer_bitrate_bps += target_bitrate.GetBitrate(si, ti);
269 spatial_layer.target_bitrate_per_temporal_layer.push_back(
270 DataRate::BitsPerSec(temporal_layer_bitrate_bps));
271 }
272 }
273 // Encoder may drop frames internally if `maxFramerate` is set.
274 spatial_layer.frame_rate_fps = std::min<uint8_t>(
275 encoder_config.simulcastStream[si].maxFramerate,
276 rtc::saturated_cast<uint8_t>(
277 (current_rate.framerate_fps * frame_rate_fraction) /
278 VideoEncoder::EncoderInfo::kMaxFramerateFraction));
279 }
280 } else if (encoder_config.numberOfSimulcastStreams == 1) {
281 // TODO(bugs.webrtc.org/12000): Implement support for AV1 with
282 // scalability.
283 const bool higher_spatial_depend_on_lower =
284 encoder_config.codecType == kVideoCodecVP9 &&
285 encoder_config.VP9().interLayerPred == InterLayerPredMode::kOn;
286 layers_allocation.resolution_and_frame_rate_is_valid = true;
287
288 std::vector<DataRate> aggregated_spatial_bitrate(
289 webrtc::kMaxTemporalStreams, DataRate::Zero());
290 for (int si = 0; si < webrtc::kMaxSpatialLayers; ++si) {
291 layers_allocation.resolution_and_frame_rate_is_valid = true;
292 if (!target_bitrate.IsSpatialLayerUsed(si) ||
293 target_bitrate.GetSpatialLayerSum(si) == 0) {
294 break;
295 }
296 layers_allocation.active_spatial_layers.emplace_back();
297 VideoLayersAllocation::SpatialLayer& spatial_layer =
298 layers_allocation.active_spatial_layers.back();
299 spatial_layer.width = encoder_config.spatialLayers[si].width;
300 spatial_layer.height = encoder_config.spatialLayers[si].height;
301 spatial_layer.rtp_stream_index = 0;
302 spatial_layer.spatial_id = si;
303 auto frame_rate_fraction =
304 VideoEncoder::EncoderInfo::kMaxFramerateFraction;
305 if (encoder_info.fps_allocation[si].size() == 1) {
306 // One TL is signalled to be used by the encoder. Do not distribute
307 // bitrate allocation across TLs (use sum at tl:0).
308 DataRate aggregated_temporal_bitrate =
309 DataRate::BitsPerSec(target_bitrate.GetSpatialLayerSum(si));
310 aggregated_spatial_bitrate[0] += aggregated_temporal_bitrate;
311 if (higher_spatial_depend_on_lower) {
312 spatial_layer.target_bitrate_per_temporal_layer.push_back(
313 aggregated_spatial_bitrate[0]);
314 } else {
315 spatial_layer.target_bitrate_per_temporal_layer.push_back(
316 aggregated_temporal_bitrate);
317 }
318 frame_rate_fraction = encoder_info.fps_allocation[si][0];
319 } else { // Temporal layers are supported.
320 DataRate aggregated_temporal_bitrate = DataRate::Zero();
321 for (size_t ti = 0;
322 ti < encoder_config.spatialLayers[si].numberOfTemporalLayers;
323 ++ti) {
324 if (!target_bitrate.HasBitrate(si, ti)) {
325 break;
326 }
327 if (ti < encoder_info.fps_allocation[si].size()) {
328 // Use frame rate of the top used temporal layer.
329 frame_rate_fraction = encoder_info.fps_allocation[si][ti];
330 }
331 aggregated_temporal_bitrate +=
332 DataRate::BitsPerSec(target_bitrate.GetBitrate(si, ti));
333 if (higher_spatial_depend_on_lower) {
334 spatial_layer.target_bitrate_per_temporal_layer.push_back(
335 aggregated_temporal_bitrate + aggregated_spatial_bitrate[ti]);
336 aggregated_spatial_bitrate[ti] += aggregated_temporal_bitrate;
337 } else {
338 spatial_layer.target_bitrate_per_temporal_layer.push_back(
339 aggregated_temporal_bitrate);
340 }
341 }
342 }
343 // Encoder may drop frames internally if `maxFramerate` is set.
344 spatial_layer.frame_rate_fps = std::min<uint8_t>(
345 encoder_config.spatialLayers[si].maxFramerate,
346 rtc::saturated_cast<uint8_t>(
347 (current_rate.framerate_fps * frame_rate_fraction) /
348 VideoEncoder::EncoderInfo::kMaxFramerateFraction));
349 }
350 }
351
352 return layers_allocation;
353 }
354
GetEncoderInfoWithBitrateLimitUpdate(const VideoEncoder::EncoderInfo & info,const VideoEncoderConfig & encoder_config,bool default_limits_allowed)355 VideoEncoder::EncoderInfo GetEncoderInfoWithBitrateLimitUpdate(
356 const VideoEncoder::EncoderInfo& info,
357 const VideoEncoderConfig& encoder_config,
358 bool default_limits_allowed) {
359 if (!default_limits_allowed || !info.resolution_bitrate_limits.empty() ||
360 encoder_config.simulcast_layers.size() <= 1) {
361 return info;
362 }
363 // Bitrate limits are not configured and more than one layer is used, use
364 // the default limits (bitrate limits are not used for simulcast).
365 VideoEncoder::EncoderInfo new_info = info;
366 new_info.resolution_bitrate_limits =
367 EncoderInfoSettings::GetDefaultSinglecastBitrateLimits(
368 encoder_config.codec_type);
369 return new_info;
370 }
371
NumActiveStreams(const std::vector<VideoStream> & streams)372 int NumActiveStreams(const std::vector<VideoStream>& streams) {
373 int num_active = 0;
374 for (const auto& stream : streams) {
375 if (stream.active)
376 ++num_active;
377 }
378 return num_active;
379 }
380
ApplyVp9BitrateLimits(const VideoEncoder::EncoderInfo & encoder_info,const VideoEncoderConfig & encoder_config,VideoCodec * codec)381 void ApplyVp9BitrateLimits(const VideoEncoder::EncoderInfo& encoder_info,
382 const VideoEncoderConfig& encoder_config,
383 VideoCodec* codec) {
384 if (codec->codecType != VideoCodecType::kVideoCodecVP9 ||
385 encoder_config.simulcast_layers.size() <= 1 ||
386 VideoStreamEncoderResourceManager::IsSimulcastOrMultipleSpatialLayers(
387 encoder_config)) {
388 // Resolution bitrate limits usage is restricted to singlecast.
389 return;
390 }
391
392 // Get bitrate limits for active stream.
393 absl::optional<uint32_t> pixels =
394 VideoStreamAdapter::GetSingleActiveLayerPixels(*codec);
395 if (!pixels.has_value()) {
396 return;
397 }
398 absl::optional<VideoEncoder::ResolutionBitrateLimits> bitrate_limits =
399 encoder_info.GetEncoderBitrateLimitsForResolution(*pixels);
400 if (!bitrate_limits.has_value()) {
401 return;
402 }
403
404 // Index for the active stream.
405 absl::optional<size_t> index;
406 for (size_t i = 0; i < encoder_config.simulcast_layers.size(); ++i) {
407 if (encoder_config.simulcast_layers[i].active)
408 index = i;
409 }
410 if (!index.has_value()) {
411 return;
412 }
413
414 int min_bitrate_bps;
415 if (encoder_config.simulcast_layers[*index].min_bitrate_bps <= 0) {
416 min_bitrate_bps = bitrate_limits->min_bitrate_bps;
417 } else {
418 min_bitrate_bps =
419 std::max(bitrate_limits->min_bitrate_bps,
420 encoder_config.simulcast_layers[*index].min_bitrate_bps);
421 }
422 int max_bitrate_bps;
423 if (encoder_config.simulcast_layers[*index].max_bitrate_bps <= 0) {
424 max_bitrate_bps = bitrate_limits->max_bitrate_bps;
425 } else {
426 max_bitrate_bps =
427 std::min(bitrate_limits->max_bitrate_bps,
428 encoder_config.simulcast_layers[*index].max_bitrate_bps);
429 }
430 if (min_bitrate_bps >= max_bitrate_bps) {
431 RTC_LOG(LS_WARNING) << "Bitrate limits not used, min_bitrate_bps "
432 << min_bitrate_bps << " >= max_bitrate_bps "
433 << max_bitrate_bps;
434 return;
435 }
436
437 for (int i = 0; i < codec->VP9()->numberOfSpatialLayers; ++i) {
438 if (codec->spatialLayers[i].active) {
439 codec->spatialLayers[i].minBitrate = min_bitrate_bps / 1000;
440 codec->spatialLayers[i].maxBitrate = max_bitrate_bps / 1000;
441 codec->spatialLayers[i].targetBitrate =
442 std::min(codec->spatialLayers[i].targetBitrate,
443 codec->spatialLayers[i].maxBitrate);
444 break;
445 }
446 }
447 }
448
ApplyEncoderBitrateLimitsIfSingleActiveStream(const VideoEncoder::EncoderInfo & encoder_info,const std::vector<VideoStream> & encoder_config_layers,std::vector<VideoStream> * streams)449 void ApplyEncoderBitrateLimitsIfSingleActiveStream(
450 const VideoEncoder::EncoderInfo& encoder_info,
451 const std::vector<VideoStream>& encoder_config_layers,
452 std::vector<VideoStream>* streams) {
453 // Apply limits if simulcast with one active stream (expect lowest).
454 bool single_active_stream =
455 streams->size() > 1 && NumActiveStreams(*streams) == 1 &&
456 !streams->front().active && NumActiveStreams(encoder_config_layers) == 1;
457 if (!single_active_stream) {
458 return;
459 }
460
461 // Index for the active stream.
462 size_t index = 0;
463 for (size_t i = 0; i < encoder_config_layers.size(); ++i) {
464 if (encoder_config_layers[i].active)
465 index = i;
466 }
467 if (streams->size() < (index + 1) || !(*streams)[index].active) {
468 return;
469 }
470
471 // Get bitrate limits for active stream.
472 absl::optional<VideoEncoder::ResolutionBitrateLimits> encoder_bitrate_limits =
473 encoder_info.GetEncoderBitrateLimitsForResolution(
474 (*streams)[index].width * (*streams)[index].height);
475 if (!encoder_bitrate_limits) {
476 return;
477 }
478
479 // If bitrate limits are set by RtpEncodingParameters, use intersection.
480 int min_bitrate_bps;
481 if (encoder_config_layers[index].min_bitrate_bps <= 0) {
482 min_bitrate_bps = encoder_bitrate_limits->min_bitrate_bps;
483 } else {
484 min_bitrate_bps = std::max(encoder_bitrate_limits->min_bitrate_bps,
485 (*streams)[index].min_bitrate_bps);
486 }
487 int max_bitrate_bps;
488 if (encoder_config_layers[index].max_bitrate_bps <= 0) {
489 max_bitrate_bps = encoder_bitrate_limits->max_bitrate_bps;
490 } else {
491 max_bitrate_bps = std::min(encoder_bitrate_limits->max_bitrate_bps,
492 (*streams)[index].max_bitrate_bps);
493 }
494 if (min_bitrate_bps >= max_bitrate_bps) {
495 RTC_LOG(LS_WARNING) << "Encoder bitrate limits"
496 << " (min=" << encoder_bitrate_limits->min_bitrate_bps
497 << ", max=" << encoder_bitrate_limits->max_bitrate_bps
498 << ") do not intersect with stream limits"
499 << " (min=" << (*streams)[index].min_bitrate_bps
500 << ", max=" << (*streams)[index].max_bitrate_bps
501 << "). Encoder bitrate limits not used.";
502 return;
503 }
504
505 (*streams)[index].min_bitrate_bps = min_bitrate_bps;
506 (*streams)[index].max_bitrate_bps = max_bitrate_bps;
507 (*streams)[index].target_bitrate_bps =
508 std::min((*streams)[index].target_bitrate_bps,
509 encoder_bitrate_limits->max_bitrate_bps);
510 }
511
ParseVp9LowTierCoreCountThreshold(const FieldTrialsView & trials)512 absl::optional<int> ParseVp9LowTierCoreCountThreshold(
513 const FieldTrialsView& trials) {
514 FieldTrialFlag disable_low_tier("Disabled");
515 FieldTrialParameter<int> max_core_count("max_core_count", 2);
516 ParseFieldTrial({&disable_low_tier, &max_core_count},
517 trials.Lookup("WebRTC-VP9-LowTierOptimizations"));
518 if (disable_low_tier.Get()) {
519 return absl::nullopt;
520 }
521 return max_core_count.Get();
522 }
523
MergeRestrictions(const std::vector<absl::optional<VideoSourceRestrictions>> & list)524 absl::optional<VideoSourceRestrictions> MergeRestrictions(
525 const std::vector<absl::optional<VideoSourceRestrictions>>& list) {
526 absl::optional<VideoSourceRestrictions> return_value;
527 for (const auto& res : list) {
528 if (!res) {
529 continue;
530 }
531 if (!return_value) {
532 return_value = *res;
533 continue;
534 }
535 return_value->UpdateMin(*res);
536 }
537 return return_value;
538 }
539
540 } // namespace
541
EncoderRateSettings()542 VideoStreamEncoder::EncoderRateSettings::EncoderRateSettings()
543 : rate_control(),
544 encoder_target(DataRate::Zero()),
545 stable_encoder_target(DataRate::Zero()) {}
546
EncoderRateSettings(const VideoBitrateAllocation & bitrate,double framerate_fps,DataRate bandwidth_allocation,DataRate encoder_target,DataRate stable_encoder_target)547 VideoStreamEncoder::EncoderRateSettings::EncoderRateSettings(
548 const VideoBitrateAllocation& bitrate,
549 double framerate_fps,
550 DataRate bandwidth_allocation,
551 DataRate encoder_target,
552 DataRate stable_encoder_target)
553 : rate_control(bitrate, framerate_fps, bandwidth_allocation),
554 encoder_target(encoder_target),
555 stable_encoder_target(stable_encoder_target) {}
556
operator ==(const EncoderRateSettings & rhs) const557 bool VideoStreamEncoder::EncoderRateSettings::operator==(
558 const EncoderRateSettings& rhs) const {
559 return rate_control == rhs.rate_control &&
560 encoder_target == rhs.encoder_target &&
561 stable_encoder_target == rhs.stable_encoder_target;
562 }
563
operator !=(const EncoderRateSettings & rhs) const564 bool VideoStreamEncoder::EncoderRateSettings::operator!=(
565 const EncoderRateSettings& rhs) const {
566 return !(*this == rhs);
567 }
568
569 class VideoStreamEncoder::DegradationPreferenceManager
570 : public DegradationPreferenceProvider {
571 public:
DegradationPreferenceManager(VideoStreamAdapter * video_stream_adapter)572 explicit DegradationPreferenceManager(
573 VideoStreamAdapter* video_stream_adapter)
574 : degradation_preference_(DegradationPreference::DISABLED),
575 is_screenshare_(false),
576 effective_degradation_preference_(DegradationPreference::DISABLED),
577 video_stream_adapter_(video_stream_adapter) {
578 RTC_DCHECK(video_stream_adapter_);
579 sequence_checker_.Detach();
580 }
581
582 ~DegradationPreferenceManager() override = default;
583
degradation_preference() const584 DegradationPreference degradation_preference() const override {
585 RTC_DCHECK_RUN_ON(&sequence_checker_);
586 return effective_degradation_preference_;
587 }
588
SetDegradationPreference(DegradationPreference degradation_preference)589 void SetDegradationPreference(DegradationPreference degradation_preference) {
590 RTC_DCHECK_RUN_ON(&sequence_checker_);
591 degradation_preference_ = degradation_preference;
592 MaybeUpdateEffectiveDegradationPreference();
593 }
594
SetIsScreenshare(bool is_screenshare)595 void SetIsScreenshare(bool is_screenshare) {
596 RTC_DCHECK_RUN_ON(&sequence_checker_);
597 is_screenshare_ = is_screenshare;
598 MaybeUpdateEffectiveDegradationPreference();
599 }
600
601 private:
MaybeUpdateEffectiveDegradationPreference()602 void MaybeUpdateEffectiveDegradationPreference()
603 RTC_RUN_ON(&sequence_checker_) {
604 DegradationPreference effective_degradation_preference =
605 (is_screenshare_ &&
606 degradation_preference_ == DegradationPreference::BALANCED)
607 ? DegradationPreference::MAINTAIN_RESOLUTION
608 : degradation_preference_;
609
610 if (effective_degradation_preference != effective_degradation_preference_) {
611 effective_degradation_preference_ = effective_degradation_preference;
612 video_stream_adapter_->SetDegradationPreference(
613 effective_degradation_preference);
614 }
615 }
616
617 RTC_NO_UNIQUE_ADDRESS SequenceChecker sequence_checker_;
618 DegradationPreference degradation_preference_
619 RTC_GUARDED_BY(&sequence_checker_);
620 bool is_screenshare_ RTC_GUARDED_BY(&sequence_checker_);
621 DegradationPreference effective_degradation_preference_
622 RTC_GUARDED_BY(&sequence_checker_);
623 VideoStreamAdapter* video_stream_adapter_ RTC_GUARDED_BY(&sequence_checker_);
624 };
625
VideoStreamEncoder(Clock * clock,uint32_t number_of_cores,VideoStreamEncoderObserver * encoder_stats_observer,const VideoStreamEncoderSettings & settings,std::unique_ptr<OveruseFrameDetector> overuse_detector,std::unique_ptr<FrameCadenceAdapterInterface> frame_cadence_adapter,std::unique_ptr<webrtc::TaskQueueBase,webrtc::TaskQueueDeleter> encoder_queue,BitrateAllocationCallbackType allocation_cb_type,const FieldTrialsView & field_trials,webrtc::VideoEncoderFactory::EncoderSelectorInterface * encoder_selector)626 VideoStreamEncoder::VideoStreamEncoder(
627 Clock* clock,
628 uint32_t number_of_cores,
629 VideoStreamEncoderObserver* encoder_stats_observer,
630 const VideoStreamEncoderSettings& settings,
631 std::unique_ptr<OveruseFrameDetector> overuse_detector,
632 std::unique_ptr<FrameCadenceAdapterInterface> frame_cadence_adapter,
633 std::unique_ptr<webrtc::TaskQueueBase, webrtc::TaskQueueDeleter>
634 encoder_queue,
635 BitrateAllocationCallbackType allocation_cb_type,
636 const FieldTrialsView& field_trials,
637 webrtc::VideoEncoderFactory::EncoderSelectorInterface* encoder_selector)
638 : field_trials_(field_trials),
639 worker_queue_(TaskQueueBase::Current()),
640 number_of_cores_(number_of_cores),
641 sink_(nullptr),
642 settings_(settings),
643 allocation_cb_type_(allocation_cb_type),
644 rate_control_settings_(RateControlSettings::ParseFromFieldTrials()),
645 encoder_selector_from_constructor_(encoder_selector),
646 encoder_selector_from_factory_(
647 encoder_selector_from_constructor_
648 ? nullptr
649 : settings.encoder_factory->GetEncoderSelector()),
650 encoder_selector_(encoder_selector_from_constructor_
651 ? encoder_selector_from_constructor_
652 : encoder_selector_from_factory_.get()),
653 encoder_stats_observer_(encoder_stats_observer),
654 cadence_callback_(*this),
655 frame_cadence_adapter_(std::move(frame_cadence_adapter)),
656 encoder_initialized_(false),
657 max_framerate_(-1),
658 pending_encoder_reconfiguration_(false),
659 pending_encoder_creation_(false),
660 crop_width_(0),
661 crop_height_(0),
662 encoder_target_bitrate_bps_(absl::nullopt),
663 max_data_payload_length_(0),
664 encoder_paused_and_dropped_frame_(false),
665 was_encode_called_since_last_initialization_(false),
666 encoder_failed_(false),
667 clock_(clock),
668 last_captured_timestamp_(0),
669 delta_ntp_internal_ms_(clock_->CurrentNtpInMilliseconds() -
670 clock_->TimeInMilliseconds()),
671 last_frame_log_ms_(clock_->TimeInMilliseconds()),
672 captured_frame_count_(0),
673 dropped_frame_cwnd_pushback_count_(0),
674 dropped_frame_encoder_block_count_(0),
675 pending_frame_post_time_us_(0),
676 accumulated_update_rect_{0, 0, 0, 0},
677 accumulated_update_rect_is_valid_(true),
678 animation_start_time_(Timestamp::PlusInfinity()),
679 cap_resolution_due_to_video_content_(false),
680 expect_resize_state_(ExpectResizeState::kNoResize),
681 fec_controller_override_(nullptr),
682 force_disable_frame_dropper_(false),
683 pending_frame_drops_(0),
684 cwnd_frame_counter_(0),
685 next_frame_types_(1, VideoFrameType::kVideoFrameDelta),
686 frame_encode_metadata_writer_(this),
687 experiment_groups_(GetExperimentGroups()),
688 automatic_animation_detection_experiment_(
689 ParseAutomatincAnimationDetectionFieldTrial()),
690 input_state_provider_(encoder_stats_observer),
691 video_stream_adapter_(
692 std::make_unique<VideoStreamAdapter>(&input_state_provider_,
693 encoder_stats_observer,
694 field_trials)),
695 degradation_preference_manager_(
696 std::make_unique<DegradationPreferenceManager>(
697 video_stream_adapter_.get())),
698 adaptation_constraints_(),
699 stream_resource_manager_(&input_state_provider_,
700 encoder_stats_observer,
701 clock_,
702 settings_.experiment_cpu_load_estimator,
703 std::move(overuse_detector),
704 degradation_preference_manager_.get(),
705 field_trials),
706 video_source_sink_controller_(/*sink=*/frame_cadence_adapter_.get(),
707 /*source=*/nullptr),
708 default_limits_allowed_(
709 !field_trials.IsEnabled("WebRTC-DefaultBitrateLimitsKillSwitch")),
710 qp_parsing_allowed_(
711 !field_trials.IsEnabled("WebRTC-QpParsingKillSwitch")),
712 switch_encoder_on_init_failures_(!field_trials.IsDisabled(
713 kSwitchEncoderOnInitializationFailuresFieldTrial)),
714 vp9_low_tier_core_threshold_(
715 ParseVp9LowTierCoreCountThreshold(field_trials)),
716 encoder_queue_(std::move(encoder_queue)) {
717 TRACE_EVENT0("webrtc", "VideoStreamEncoder::VideoStreamEncoder");
718 RTC_DCHECK_RUN_ON(worker_queue_);
719 RTC_DCHECK(encoder_stats_observer);
720 RTC_DCHECK_GE(number_of_cores, 1);
721
722 frame_cadence_adapter_->Initialize(&cadence_callback_);
723 stream_resource_manager_.Initialize(encoder_queue_.Get());
724
__anon1bb4af870202null725 encoder_queue_.PostTask([this] {
726 RTC_DCHECK_RUN_ON(&encoder_queue_);
727
728 resource_adaptation_processor_ =
729 std::make_unique<ResourceAdaptationProcessor>(
730 video_stream_adapter_.get());
731
732 stream_resource_manager_.SetAdaptationProcessor(
733 resource_adaptation_processor_.get(), video_stream_adapter_.get());
734 resource_adaptation_processor_->AddResourceLimitationsListener(
735 &stream_resource_manager_);
736 video_stream_adapter_->AddRestrictionsListener(&stream_resource_manager_);
737 video_stream_adapter_->AddRestrictionsListener(this);
738 stream_resource_manager_.MaybeInitializePixelLimitResource();
739
740 // Add the stream resource manager's resources to the processor.
741 adaptation_constraints_ = stream_resource_manager_.AdaptationConstraints();
742 for (auto* constraint : adaptation_constraints_) {
743 video_stream_adapter_->AddAdaptationConstraint(constraint);
744 }
745 });
746 }
747
~VideoStreamEncoder()748 VideoStreamEncoder::~VideoStreamEncoder() {
749 RTC_DCHECK_RUN_ON(worker_queue_);
750 RTC_DCHECK(!video_source_sink_controller_.HasSource())
751 << "Must call ::Stop() before destruction.";
752 }
753
Stop()754 void VideoStreamEncoder::Stop() {
755 RTC_DCHECK_RUN_ON(worker_queue_);
756 video_source_sink_controller_.SetSource(nullptr);
757
758 rtc::Event shutdown_event;
759 absl::Cleanup shutdown = [&shutdown_event] { shutdown_event.Set(); };
760 encoder_queue_.PostTask(
761 [this, shutdown = std::move(shutdown)] {
762 RTC_DCHECK_RUN_ON(&encoder_queue_);
763 if (resource_adaptation_processor_) {
764 stream_resource_manager_.StopManagedResources();
765 for (auto* constraint : adaptation_constraints_) {
766 video_stream_adapter_->RemoveAdaptationConstraint(constraint);
767 }
768 for (auto& resource : additional_resources_) {
769 stream_resource_manager_.RemoveResource(resource);
770 }
771 additional_resources_.clear();
772 video_stream_adapter_->RemoveRestrictionsListener(this);
773 video_stream_adapter_->RemoveRestrictionsListener(
774 &stream_resource_manager_);
775 resource_adaptation_processor_->RemoveResourceLimitationsListener(
776 &stream_resource_manager_);
777 stream_resource_manager_.SetAdaptationProcessor(nullptr, nullptr);
778 resource_adaptation_processor_.reset();
779 }
780 rate_allocator_ = nullptr;
781 ReleaseEncoder();
782 encoder_ = nullptr;
783 frame_cadence_adapter_ = nullptr;
784 });
785 shutdown_event.Wait(rtc::Event::kForever);
786 }
787
SetFecControllerOverride(FecControllerOverride * fec_controller_override)788 void VideoStreamEncoder::SetFecControllerOverride(
789 FecControllerOverride* fec_controller_override) {
790 encoder_queue_.PostTask([this, fec_controller_override] {
791 RTC_DCHECK_RUN_ON(&encoder_queue_);
792 RTC_DCHECK(!fec_controller_override_);
793 fec_controller_override_ = fec_controller_override;
794 if (encoder_) {
795 encoder_->SetFecControllerOverride(fec_controller_override_);
796 }
797 });
798 }
799
AddAdaptationResource(rtc::scoped_refptr<Resource> resource)800 void VideoStreamEncoder::AddAdaptationResource(
801 rtc::scoped_refptr<Resource> resource) {
802 RTC_DCHECK_RUN_ON(worker_queue_);
803 TRACE_EVENT0("webrtc", "VideoStreamEncoder::AddAdaptationResource");
804 // Map any externally added resources as kCpu for the sake of stats reporting.
805 // TODO(hbos): Make the manager map any unknown resources to kCpu and get rid
806 // of this MapResourceToReason() call.
807 TRACE_EVENT_ASYNC_BEGIN0(
808 "webrtc", "VideoStreamEncoder::AddAdaptationResource(latency)", this);
809 encoder_queue_.PostTask([this, resource = std::move(resource)] {
810 TRACE_EVENT_ASYNC_END0(
811 "webrtc", "VideoStreamEncoder::AddAdaptationResource(latency)", this);
812 RTC_DCHECK_RUN_ON(&encoder_queue_);
813 additional_resources_.push_back(resource);
814 stream_resource_manager_.AddResource(resource, VideoAdaptationReason::kCpu);
815 });
816 }
817
818 std::vector<rtc::scoped_refptr<Resource>>
GetAdaptationResources()819 VideoStreamEncoder::GetAdaptationResources() {
820 RTC_DCHECK_RUN_ON(worker_queue_);
821 // In practice, this method is only called by tests to verify operations that
822 // run on the encoder queue. So rather than force PostTask() operations to
823 // be accompanied by an event and a `Wait()`, we'll use PostTask + Wait()
824 // here.
825 rtc::Event event;
826 std::vector<rtc::scoped_refptr<Resource>> resources;
827 encoder_queue_.PostTask([&] {
828 RTC_DCHECK_RUN_ON(&encoder_queue_);
829 resources = resource_adaptation_processor_->GetResources();
830 event.Set();
831 });
832 event.Wait(rtc::Event::kForever);
833 return resources;
834 }
835
SetSource(rtc::VideoSourceInterface<VideoFrame> * source,const DegradationPreference & degradation_preference)836 void VideoStreamEncoder::SetSource(
837 rtc::VideoSourceInterface<VideoFrame>* source,
838 const DegradationPreference& degradation_preference) {
839 RTC_DCHECK_RUN_ON(worker_queue_);
840 video_source_sink_controller_.SetSource(source);
841 input_state_provider_.OnHasInputChanged(source);
842
843 // This may trigger reconfiguring the QualityScaler on the encoder queue.
844 encoder_queue_.PostTask([this, degradation_preference] {
845 RTC_DCHECK_RUN_ON(&encoder_queue_);
846 degradation_preference_manager_->SetDegradationPreference(
847 degradation_preference);
848 stream_resource_manager_.SetDegradationPreferences(degradation_preference);
849 if (encoder_) {
850 stream_resource_manager_.ConfigureQualityScaler(
851 encoder_->GetEncoderInfo());
852 stream_resource_manager_.ConfigureBandwidthQualityScaler(
853 encoder_->GetEncoderInfo());
854 }
855 });
856 }
857
SetSink(EncoderSink * sink,bool rotation_applied)858 void VideoStreamEncoder::SetSink(EncoderSink* sink, bool rotation_applied) {
859 RTC_DCHECK_RUN_ON(worker_queue_);
860 video_source_sink_controller_.SetRotationApplied(rotation_applied);
861 video_source_sink_controller_.PushSourceSinkSettings();
862
863 encoder_queue_.PostTask([this, sink] {
864 RTC_DCHECK_RUN_ON(&encoder_queue_);
865 sink_ = sink;
866 });
867 }
868
SetStartBitrate(int start_bitrate_bps)869 void VideoStreamEncoder::SetStartBitrate(int start_bitrate_bps) {
870 encoder_queue_.PostTask([this, start_bitrate_bps] {
871 RTC_DCHECK_RUN_ON(&encoder_queue_);
872 RTC_LOG(LS_INFO) << "SetStartBitrate " << start_bitrate_bps;
873 encoder_target_bitrate_bps_ =
874 start_bitrate_bps != 0 ? absl::optional<uint32_t>(start_bitrate_bps)
875 : absl::nullopt;
876 stream_resource_manager_.SetStartBitrate(
877 DataRate::BitsPerSec(start_bitrate_bps));
878 });
879 }
880
ConfigureEncoder(VideoEncoderConfig config,size_t max_data_payload_length)881 void VideoStreamEncoder::ConfigureEncoder(VideoEncoderConfig config,
882 size_t max_data_payload_length) {
883 ConfigureEncoder(std::move(config), max_data_payload_length, nullptr);
884 }
885
ConfigureEncoder(VideoEncoderConfig config,size_t max_data_payload_length,SetParametersCallback callback)886 void VideoStreamEncoder::ConfigureEncoder(VideoEncoderConfig config,
887 size_t max_data_payload_length,
888 SetParametersCallback callback) {
889 RTC_DCHECK_RUN_ON(worker_queue_);
890 encoder_queue_.PostTask(
891 [this, config = std::move(config), max_data_payload_length,
892 callback = std::move(callback)]() mutable {
893 RTC_DCHECK_RUN_ON(&encoder_queue_);
894 RTC_DCHECK(sink_);
895 RTC_LOG(LS_INFO) << "ConfigureEncoder requested.";
896
897 // Set up the frame cadence adapter according to if we're going to do
898 // screencast. The final number of spatial layers is based on info
899 // in `send_codec_`, which is computed based on incoming frame
900 // dimensions which can only be determined later.
901 //
902 // Note: zero-hertz mode isn't enabled by this alone. Constraints also
903 // have to be set up with min_fps = 0 and max_fps > 0.
904 if (config.content_type == VideoEncoderConfig::ContentType::kScreen) {
905 frame_cadence_adapter_->SetZeroHertzModeEnabled(
906 FrameCadenceAdapterInterface::ZeroHertzModeParams{});
907 } else {
908 frame_cadence_adapter_->SetZeroHertzModeEnabled(absl::nullopt);
909 }
910
911 pending_encoder_creation_ =
912 (!encoder_ || encoder_config_.video_format != config.video_format ||
913 max_data_payload_length_ != max_data_payload_length);
914 encoder_config_ = std::move(config);
915 max_data_payload_length_ = max_data_payload_length;
916 pending_encoder_reconfiguration_ = true;
917
918 // Reconfigure the encoder now if the frame resolution is known.
919 // Otherwise, the reconfiguration is deferred until the next frame to
920 // minimize the number of reconfigurations. The codec configuration
921 // depends on incoming video frame size.
922 if (last_frame_info_) {
923 if (callback) {
924 encoder_configuration_callbacks_.push_back(std::move(callback));
925 }
926
927 ReconfigureEncoder();
928 } else {
929 webrtc::InvokeSetParametersCallback(callback, webrtc::RTCError::OK());
930 }
931 });
932 }
933
934 // We should reduce the number of 'full' ReconfigureEncoder(). If only need
935 // subset of it at runtime, consider handle it in
936 // VideoStreamEncoder::EncodeVideoFrame() when encoder_info_ != info.
ReconfigureEncoder()937 void VideoStreamEncoder::ReconfigureEncoder() {
938 // Running on the encoder queue.
939 RTC_DCHECK(pending_encoder_reconfiguration_);
940
941 bool encoder_reset_required = false;
942 if (pending_encoder_creation_) {
943 // Destroy existing encoder instance before creating a new one. Otherwise
944 // attempt to create another instance will fail if encoder factory
945 // supports only single instance of encoder of given type.
946 encoder_.reset();
947
948 encoder_ = settings_.encoder_factory->CreateVideoEncoder(
949 encoder_config_.video_format);
950 if (!encoder_) {
951 RTC_LOG(LS_ERROR) << "CreateVideoEncoder failed, failing encoder format: "
952 << encoder_config_.video_format.ToString();
953 RequestEncoderSwitch();
954 return;
955 }
956
957 if (encoder_selector_) {
958 encoder_selector_->OnCurrentEncoder(encoder_config_.video_format);
959 }
960
961 encoder_->SetFecControllerOverride(fec_controller_override_);
962
963 encoder_reset_required = true;
964 }
965
966 // TODO(webrtc:14451) : Move AlignmentAdjuster into EncoderStreamFactory
967 // Possibly adjusts scale_resolution_down_by in `encoder_config_` to limit the
968 // alignment value.
969 AlignmentAdjuster::GetAlignmentAndMaybeAdjustScaleFactors(
970 encoder_->GetEncoderInfo(), &encoder_config_, absl::nullopt);
971
972 std::vector<VideoStream> streams;
973 if (encoder_config_.video_stream_factory) {
974 // Note: only tests set their own EncoderStreamFactory...
975 streams = encoder_config_.video_stream_factory->CreateEncoderStreams(
976 last_frame_info_->width, last_frame_info_->height, encoder_config_);
977 } else {
978 rtc::scoped_refptr<VideoEncoderConfig::VideoStreamFactoryInterface>
979 factory = rtc::make_ref_counted<cricket::EncoderStreamFactory>(
980 encoder_config_.video_format.name, encoder_config_.max_qp,
981 encoder_config_.content_type ==
982 webrtc::VideoEncoderConfig::ContentType::kScreen,
983 encoder_config_.legacy_conference_mode, encoder_->GetEncoderInfo(),
984 MergeRestrictions({latest_restrictions_, animate_restrictions_}),
985 &field_trials_);
986
987 streams = factory->CreateEncoderStreams(
988 last_frame_info_->width, last_frame_info_->height, encoder_config_);
989 }
990
991 // TODO(webrtc:14451) : Move AlignmentAdjuster into EncoderStreamFactory
992 // Get alignment when actual number of layers are known.
993 int alignment = AlignmentAdjuster::GetAlignmentAndMaybeAdjustScaleFactors(
994 encoder_->GetEncoderInfo(), &encoder_config_, streams.size());
995
996 // Check that the higher layers do not try to set number of temporal layers
997 // to less than 1.
998 // TODO(brandtr): Get rid of the wrapping optional as it serves no purpose
999 // at this layer.
1000 #if RTC_DCHECK_IS_ON
1001 for (const auto& stream : streams) {
1002 RTC_DCHECK_GE(stream.num_temporal_layers.value_or(1), 1);
1003 }
1004 #endif
1005
1006 // TODO(ilnik): If configured resolution is significantly less than provided,
1007 // e.g. because there are not enough SSRCs for all simulcast streams,
1008 // signal new resolutions via SinkWants to video source.
1009
1010 // Stream dimensions may be not equal to given because of a simulcast
1011 // restrictions.
1012 auto highest_stream = absl::c_max_element(
1013 streams, [](const webrtc::VideoStream& a, const webrtc::VideoStream& b) {
1014 return std::tie(a.width, a.height) < std::tie(b.width, b.height);
1015 });
1016 int highest_stream_width = static_cast<int>(highest_stream->width);
1017 int highest_stream_height = static_cast<int>(highest_stream->height);
1018 // Dimension may be reduced to be, e.g. divisible by 4.
1019 RTC_CHECK_GE(last_frame_info_->width, highest_stream_width);
1020 RTC_CHECK_GE(last_frame_info_->height, highest_stream_height);
1021 crop_width_ = last_frame_info_->width - highest_stream_width;
1022 crop_height_ = last_frame_info_->height - highest_stream_height;
1023
1024 if (!encoder_->GetEncoderInfo().is_qp_trusted.value_or(true)) {
1025 // when qp is not trusted, we priorities to using the
1026 // |resolution_bitrate_limits| provided by the decoder.
1027 const std::vector<VideoEncoder::ResolutionBitrateLimits>& bitrate_limits =
1028 encoder_->GetEncoderInfo().resolution_bitrate_limits.empty()
1029 ? EncoderInfoSettings::
1030 GetDefaultSinglecastBitrateLimitsWhenQpIsUntrusted()
1031 : encoder_->GetEncoderInfo().resolution_bitrate_limits;
1032
1033 // For BandwidthQualityScaler, its implement based on a certain pixel_count
1034 // correspond a certain bps interval. In fact, WebRTC default max_bps is
1035 // 2500Kbps when width * height > 960 * 540. For example, we assume:
1036 // 1.the camera support 1080p.
1037 // 2.ResolutionBitrateLimits set 720p bps interval is [1500Kbps,2000Kbps].
1038 // 3.ResolutionBitrateLimits set 1080p bps interval is [2000Kbps,2500Kbps].
1039 // We will never be stable at 720p due to actual encoding bps of 720p and
1040 // 1080p are both 2500Kbps. So it is necessary to do a linear interpolation
1041 // to get a certain bitrate for certain pixel_count. It also doesn't work
1042 // for 960*540 and 640*520, we will nerver be stable at 640*520 due to their
1043 // |target_bitrate_bps| are both 2000Kbps.
1044 absl::optional<VideoEncoder::ResolutionBitrateLimits>
1045 qp_untrusted_bitrate_limit = EncoderInfoSettings::
1046 GetSinglecastBitrateLimitForResolutionWhenQpIsUntrusted(
1047 last_frame_info_->width * last_frame_info_->height,
1048 bitrate_limits);
1049
1050 if (qp_untrusted_bitrate_limit) {
1051 // bandwidth_quality_scaler is only used for singlecast.
1052 if (streams.size() == 1 && encoder_config_.simulcast_layers.size() == 1) {
1053 streams.back().min_bitrate_bps =
1054 qp_untrusted_bitrate_limit->min_bitrate_bps;
1055 streams.back().max_bitrate_bps =
1056 qp_untrusted_bitrate_limit->max_bitrate_bps;
1057 // If it is screen share mode, the minimum value of max_bitrate should
1058 // be greater than/equal to 1200kbps.
1059 if (encoder_config_.content_type ==
1060 VideoEncoderConfig::ContentType::kScreen) {
1061 streams.back().max_bitrate_bps = std::max(
1062 streams.back().max_bitrate_bps, kDefaultMinScreenSharebps);
1063 }
1064 streams.back().target_bitrate_bps =
1065 qp_untrusted_bitrate_limit->max_bitrate_bps;
1066 }
1067 }
1068 } else {
1069 absl::optional<VideoEncoder::ResolutionBitrateLimits>
1070 encoder_bitrate_limits =
1071 encoder_->GetEncoderInfo().GetEncoderBitrateLimitsForResolution(
1072 last_frame_info_->width * last_frame_info_->height);
1073
1074 if (encoder_bitrate_limits) {
1075 if (streams.size() == 1 && encoder_config_.simulcast_layers.size() == 1) {
1076 // Bitrate limits can be set by app (in SDP or RtpEncodingParameters)
1077 // or/and can be provided by encoder. In presence of both set of
1078 // limits, the final set is derived as their intersection.
1079 int min_bitrate_bps;
1080 if (encoder_config_.simulcast_layers.empty() ||
1081 encoder_config_.simulcast_layers[0].min_bitrate_bps <= 0) {
1082 min_bitrate_bps = encoder_bitrate_limits->min_bitrate_bps;
1083 } else {
1084 min_bitrate_bps = std::max(encoder_bitrate_limits->min_bitrate_bps,
1085 streams.back().min_bitrate_bps);
1086 }
1087
1088 int max_bitrate_bps;
1089 // We don't check encoder_config_.simulcast_layers[0].max_bitrate_bps
1090 // here since encoder_config_.max_bitrate_bps is derived from it (as
1091 // well as from other inputs).
1092 if (encoder_config_.max_bitrate_bps <= 0) {
1093 max_bitrate_bps = encoder_bitrate_limits->max_bitrate_bps;
1094 } else {
1095 max_bitrate_bps = std::min(encoder_bitrate_limits->max_bitrate_bps,
1096 streams.back().max_bitrate_bps);
1097 }
1098
1099 if (min_bitrate_bps < max_bitrate_bps) {
1100 streams.back().min_bitrate_bps = min_bitrate_bps;
1101 streams.back().max_bitrate_bps = max_bitrate_bps;
1102 streams.back().target_bitrate_bps =
1103 std::min(streams.back().target_bitrate_bps,
1104 encoder_bitrate_limits->max_bitrate_bps);
1105 } else {
1106 RTC_LOG(LS_WARNING)
1107 << "Bitrate limits provided by encoder"
1108 << " (min=" << encoder_bitrate_limits->min_bitrate_bps
1109 << ", max=" << encoder_bitrate_limits->max_bitrate_bps
1110 << ") do not intersect with limits set by app"
1111 << " (min=" << streams.back().min_bitrate_bps
1112 << ", max=" << encoder_config_.max_bitrate_bps
1113 << "). The app bitrate limits will be used.";
1114 }
1115 }
1116 }
1117 }
1118
1119 ApplyEncoderBitrateLimitsIfSingleActiveStream(
1120 GetEncoderInfoWithBitrateLimitUpdate(
1121 encoder_->GetEncoderInfo(), encoder_config_, default_limits_allowed_),
1122 encoder_config_.simulcast_layers, &streams);
1123
1124 VideoCodec codec;
1125 if (!VideoCodecInitializer::SetupCodec(encoder_config_, streams, &codec)) {
1126 RTC_LOG(LS_ERROR) << "Failed to create encoder configuration.";
1127 }
1128
1129 if (encoder_config_.codec_type == kVideoCodecVP9) {
1130 // Spatial layers configuration might impose some parity restrictions,
1131 // thus some cropping might be needed.
1132 crop_width_ = last_frame_info_->width - codec.width;
1133 crop_height_ = last_frame_info_->height - codec.height;
1134 ApplyVp9BitrateLimits(GetEncoderInfoWithBitrateLimitUpdate(
1135 encoder_->GetEncoderInfo(), encoder_config_,
1136 default_limits_allowed_),
1137 encoder_config_, &codec);
1138 }
1139
1140 char log_stream_buf[4 * 1024];
1141 rtc::SimpleStringBuilder log_stream(log_stream_buf);
1142 log_stream << "ReconfigureEncoder:\n";
1143 log_stream << "Simulcast streams:\n";
1144 for (size_t i = 0; i < codec.numberOfSimulcastStreams; ++i) {
1145 log_stream << i << ": " << codec.simulcastStream[i].width << "x"
1146 << codec.simulcastStream[i].height
1147 << " min_kbps: " << codec.simulcastStream[i].minBitrate
1148 << " target_kbps: " << codec.simulcastStream[i].targetBitrate
1149 << " max_kbps: " << codec.simulcastStream[i].maxBitrate
1150 << " max_fps: " << codec.simulcastStream[i].maxFramerate
1151 << " max_qp: " << codec.simulcastStream[i].qpMax
1152 << " num_tl: " << codec.simulcastStream[i].numberOfTemporalLayers
1153 << " active: "
1154 << (codec.simulcastStream[i].active ? "true" : "false") << "\n";
1155 }
1156 if (encoder_config_.codec_type == kVideoCodecVP9) {
1157 size_t num_spatial_layers = codec.VP9()->numberOfSpatialLayers;
1158 log_stream << "Spatial layers:\n";
1159 for (size_t i = 0; i < num_spatial_layers; ++i) {
1160 log_stream << i << ": " << codec.spatialLayers[i].width << "x"
1161 << codec.spatialLayers[i].height
1162 << " min_kbps: " << codec.spatialLayers[i].minBitrate
1163 << " target_kbps: " << codec.spatialLayers[i].targetBitrate
1164 << " max_kbps: " << codec.spatialLayers[i].maxBitrate
1165 << " max_fps: " << codec.spatialLayers[i].maxFramerate
1166 << " max_qp: " << codec.spatialLayers[i].qpMax
1167 << " num_tl: " << codec.spatialLayers[i].numberOfTemporalLayers
1168 << " active: "
1169 << (codec.spatialLayers[i].active ? "true" : "false") << "\n";
1170 }
1171 }
1172 RTC_LOG(LS_INFO) << log_stream.str();
1173
1174 codec.startBitrate = std::max(encoder_target_bitrate_bps_.value_or(0) / 1000,
1175 codec.minBitrate);
1176 codec.startBitrate = std::min(codec.startBitrate, codec.maxBitrate);
1177 codec.expect_encode_from_texture = last_frame_info_->is_texture;
1178 // Make sure the start bit rate is sane...
1179 RTC_DCHECK_LE(codec.startBitrate, 1000000);
1180 max_framerate_ = codec.maxFramerate;
1181
1182 // Inform source about max configured framerate,
1183 // requested_resolution and which layers are active.
1184 int max_framerate = 0;
1185 // Is any layer active.
1186 bool active = false;
1187 // The max requested_resolution.
1188 absl::optional<rtc::VideoSinkWants::FrameSize> requested_resolution;
1189 for (const auto& stream : streams) {
1190 max_framerate = std::max(stream.max_framerate, max_framerate);
1191 active |= stream.active;
1192 // Note: we propagate the highest requested_resolution regardless
1193 // if layer is active or not.
1194 if (stream.requested_resolution) {
1195 if (!requested_resolution) {
1196 requested_resolution.emplace(stream.requested_resolution->width,
1197 stream.requested_resolution->height);
1198 } else {
1199 requested_resolution.emplace(
1200 std::max(stream.requested_resolution->width,
1201 requested_resolution->width),
1202 std::max(stream.requested_resolution->height,
1203 requested_resolution->height));
1204 }
1205 }
1206 }
1207
1208 // The resolutions that we're actually encoding with.
1209 std::vector<rtc::VideoSinkWants::FrameSize> encoder_resolutions;
1210 // TODO(hbos): For the case of SVC, also make use of `codec.spatialLayers`.
1211 // For now, SVC layers are handled by the VP9 encoder.
1212 for (const auto& simulcastStream : codec.simulcastStream) {
1213 if (!simulcastStream.active)
1214 continue;
1215 encoder_resolutions.emplace_back(simulcastStream.width,
1216 simulcastStream.height);
1217 }
1218
1219 worker_queue_->PostTask(SafeTask(
1220 task_safety_.flag(),
1221 [this, max_framerate, alignment,
1222 encoder_resolutions = std::move(encoder_resolutions),
1223 requested_resolution = std::move(requested_resolution), active]() {
1224 RTC_DCHECK_RUN_ON(worker_queue_);
1225 if (max_framerate !=
1226 video_source_sink_controller_.frame_rate_upper_limit() ||
1227 alignment != video_source_sink_controller_.resolution_alignment() ||
1228 encoder_resolutions !=
1229 video_source_sink_controller_.resolutions() ||
1230 (video_source_sink_controller_.requested_resolution() !=
1231 requested_resolution) ||
1232 (video_source_sink_controller_.active() != active)) {
1233 video_source_sink_controller_.SetFrameRateUpperLimit(max_framerate);
1234 video_source_sink_controller_.SetResolutionAlignment(alignment);
1235 video_source_sink_controller_.SetResolutions(
1236 std::move(encoder_resolutions));
1237 video_source_sink_controller_.SetRequestedResolution(
1238 requested_resolution);
1239 video_source_sink_controller_.SetActive(active);
1240 video_source_sink_controller_.PushSourceSinkSettings();
1241 }
1242 }));
1243
1244 rate_allocator_ =
1245 settings_.bitrate_allocator_factory->CreateVideoBitrateAllocator(codec);
1246 rate_allocator_->SetLegacyConferenceMode(
1247 encoder_config_.legacy_conference_mode);
1248
1249 // Reset (release existing encoder) if one exists and anything except
1250 // start bitrate or max framerate has changed.
1251 if (!encoder_reset_required) {
1252 encoder_reset_required = RequiresEncoderReset(
1253 send_codec_, codec, was_encode_called_since_last_initialization_);
1254 }
1255
1256 if (codec.codecType == VideoCodecType::kVideoCodecVP9 &&
1257 number_of_cores_ <= vp9_low_tier_core_threshold_.value_or(0)) {
1258 codec.SetVideoEncoderComplexity(VideoCodecComplexity::kComplexityLow);
1259 }
1260
1261 send_codec_ = codec;
1262
1263 // Keep the same encoder, as long as the video_format is unchanged.
1264 // Encoder creation block is split in two since EncoderInfo needed to start
1265 // CPU adaptation with the correct settings should be polled after
1266 // encoder_->InitEncode().
1267 if (encoder_reset_required) {
1268 ReleaseEncoder();
1269 const size_t max_data_payload_length = max_data_payload_length_ > 0
1270 ? max_data_payload_length_
1271 : kDefaultPayloadSize;
1272 if (encoder_->InitEncode(
1273 &send_codec_,
1274 VideoEncoder::Settings(settings_.capabilities, number_of_cores_,
1275 max_data_payload_length)) != 0) {
1276 RTC_LOG(LS_ERROR) << "Failed to initialize the encoder associated with "
1277 "codec type: "
1278 << CodecTypeToPayloadString(send_codec_.codecType)
1279 << " (" << send_codec_.codecType << ")";
1280 ReleaseEncoder();
1281 } else {
1282 encoder_initialized_ = true;
1283 encoder_->RegisterEncodeCompleteCallback(this);
1284 frame_encode_metadata_writer_.OnEncoderInit(send_codec_);
1285 next_frame_types_.clear();
1286 next_frame_types_.resize(
1287 std::max(static_cast<int>(codec.numberOfSimulcastStreams), 1),
1288 VideoFrameType::kVideoFrameKey);
1289 }
1290
1291 frame_encode_metadata_writer_.Reset();
1292 last_encode_info_ms_ = absl::nullopt;
1293 was_encode_called_since_last_initialization_ = false;
1294 }
1295
1296 // Inform dependents of updated encoder settings.
1297 OnEncoderSettingsChanged();
1298
1299 if (encoder_initialized_) {
1300 RTC_LOG(LS_VERBOSE) << " max bitrate " << codec.maxBitrate
1301 << " start bitrate " << codec.startBitrate
1302 << " max frame rate " << codec.maxFramerate
1303 << " max payload size " << max_data_payload_length_;
1304 } else {
1305 RTC_LOG(LS_ERROR) << "Failed to configure encoder.";
1306 rate_allocator_ = nullptr;
1307 }
1308
1309 if (pending_encoder_creation_) {
1310 stream_resource_manager_.ConfigureEncodeUsageResource();
1311 pending_encoder_creation_ = false;
1312 }
1313
1314 int num_layers;
1315 if (codec.codecType == kVideoCodecVP8) {
1316 num_layers = codec.VP8()->numberOfTemporalLayers;
1317 } else if (codec.codecType == kVideoCodecVP9) {
1318 num_layers = codec.VP9()->numberOfTemporalLayers;
1319 } else if (codec.codecType == kVideoCodecH264) {
1320 num_layers = codec.H264()->numberOfTemporalLayers;
1321 } else if (codec.codecType == kVideoCodecGeneric &&
1322 codec.numberOfSimulcastStreams > 0) {
1323 // This is mainly for unit testing, disabling frame dropping.
1324 // TODO(sprang): Add a better way to disable frame dropping.
1325 num_layers = codec.simulcastStream[0].numberOfTemporalLayers;
1326 } else {
1327 num_layers = 1;
1328 }
1329
1330 frame_dropper_.Reset();
1331 frame_dropper_.SetRates(codec.startBitrate, max_framerate_);
1332 // Force-disable frame dropper if either:
1333 // * We have screensharing with layers.
1334 // * "WebRTC-FrameDropper" field trial is "Disabled".
1335 force_disable_frame_dropper_ =
1336 field_trials_.IsDisabled(kFrameDropperFieldTrial) ||
1337 (num_layers > 1 && codec.mode == VideoCodecMode::kScreensharing);
1338
1339 VideoEncoder::EncoderInfo info = encoder_->GetEncoderInfo();
1340 if (rate_control_settings_.UseEncoderBitrateAdjuster()) {
1341 bitrate_adjuster_ = std::make_unique<EncoderBitrateAdjuster>(codec);
1342 bitrate_adjuster_->OnEncoderInfo(info);
1343 }
1344
1345 if (rate_allocator_ && last_encoder_rate_settings_) {
1346 // We have a new rate allocator instance and already configured target
1347 // bitrate. Update the rate allocation and notify observers.
1348 // We must invalidate the last_encoder_rate_settings_ to ensure
1349 // the changes get propagated to all listeners.
1350 EncoderRateSettings rate_settings = *last_encoder_rate_settings_;
1351 last_encoder_rate_settings_.reset();
1352 rate_settings.rate_control.framerate_fps = GetInputFramerateFps();
1353
1354 SetEncoderRates(UpdateBitrateAllocation(rate_settings));
1355 }
1356
1357 encoder_stats_observer_->OnEncoderReconfigured(encoder_config_, streams);
1358
1359 pending_encoder_reconfiguration_ = false;
1360
1361 bool is_svc = false;
1362 // Set min_bitrate_bps, max_bitrate_bps, and max padding bit rate for VP9
1363 // and leave only one stream containing all necessary information.
1364 if (encoder_config_.codec_type == kVideoCodecVP9) {
1365 // Lower max bitrate to the level codec actually can produce.
1366 streams[0].max_bitrate_bps =
1367 std::min(streams[0].max_bitrate_bps,
1368 SvcRateAllocator::GetMaxBitrate(codec).bps<int>());
1369 streams[0].min_bitrate_bps = codec.spatialLayers[0].minBitrate * 1000;
1370 // target_bitrate_bps specifies the maximum padding bitrate.
1371 streams[0].target_bitrate_bps =
1372 SvcRateAllocator::GetPaddingBitrate(codec).bps<int>();
1373 streams[0].width = streams.back().width;
1374 streams[0].height = streams.back().height;
1375 is_svc = codec.VP9()->numberOfSpatialLayers > 1;
1376 streams.resize(1);
1377 }
1378
1379 sink_->OnEncoderConfigurationChanged(
1380 std::move(streams), is_svc, encoder_config_.content_type,
1381 encoder_config_.min_transmit_bitrate_bps);
1382
1383 stream_resource_manager_.ConfigureQualityScaler(info);
1384 stream_resource_manager_.ConfigureBandwidthQualityScaler(info);
1385
1386 webrtc::RTCError encoder_configuration_result = webrtc::RTCError::OK();
1387
1388 if (!encoder_initialized_) {
1389 RTC_LOG(LS_WARNING) << "Failed to initialize "
1390 << CodecTypeToPayloadString(codec.codecType)
1391 << " encoder."
1392 << "switch_encoder_on_init_failures: "
1393 << switch_encoder_on_init_failures_;
1394
1395 if (switch_encoder_on_init_failures_) {
1396 RequestEncoderSwitch();
1397 } else {
1398 encoder_configuration_result =
1399 webrtc::RTCError(RTCErrorType::UNSUPPORTED_OPERATION);
1400 }
1401 }
1402
1403 if (!encoder_configuration_callbacks_.empty()) {
1404 for (auto& callback : encoder_configuration_callbacks_) {
1405 webrtc::InvokeSetParametersCallback(callback,
1406 encoder_configuration_result);
1407 }
1408 encoder_configuration_callbacks_.clear();
1409 }
1410 }
1411
RequestEncoderSwitch()1412 void VideoStreamEncoder::RequestEncoderSwitch() {
1413 bool is_encoder_switching_supported =
1414 settings_.encoder_switch_request_callback != nullptr;
1415 bool is_encoder_selector_available = encoder_selector_ != nullptr;
1416
1417 RTC_LOG(LS_INFO) << "RequestEncoderSwitch."
1418 << " is_encoder_selector_available: "
1419 << is_encoder_selector_available
1420 << " is_encoder_switching_supported: "
1421 << is_encoder_switching_supported;
1422
1423 if (!is_encoder_switching_supported) {
1424 return;
1425 }
1426
1427 // If encoder selector is available, switch to the encoder it prefers.
1428 // Otherwise try switching to VP8 (default WebRTC codec).
1429 absl::optional<SdpVideoFormat> preferred_fallback_encoder;
1430 if (is_encoder_selector_available) {
1431 preferred_fallback_encoder = encoder_selector_->OnEncoderBroken();
1432 }
1433
1434 if (!preferred_fallback_encoder) {
1435 preferred_fallback_encoder =
1436 SdpVideoFormat(CodecTypeToPayloadString(kVideoCodecVP8));
1437 }
1438
1439 settings_.encoder_switch_request_callback->RequestEncoderSwitch(
1440 *preferred_fallback_encoder, /*allow_default_fallback=*/true);
1441 }
1442
OnEncoderSettingsChanged()1443 void VideoStreamEncoder::OnEncoderSettingsChanged() {
1444 EncoderSettings encoder_settings(
1445 GetEncoderInfoWithBitrateLimitUpdate(
1446 encoder_->GetEncoderInfo(), encoder_config_, default_limits_allowed_),
1447 encoder_config_.Copy(), send_codec_);
1448 stream_resource_manager_.SetEncoderSettings(encoder_settings);
1449 input_state_provider_.OnEncoderSettingsChanged(encoder_settings);
1450 bool is_screenshare = encoder_settings.encoder_config().content_type ==
1451 VideoEncoderConfig::ContentType::kScreen;
1452 degradation_preference_manager_->SetIsScreenshare(is_screenshare);
1453 if (is_screenshare) {
1454 frame_cadence_adapter_->SetZeroHertzModeEnabled(
1455 FrameCadenceAdapterInterface::ZeroHertzModeParams{
1456 send_codec_.numberOfSimulcastStreams});
1457 }
1458 }
1459
OnFrame(Timestamp post_time,int frames_scheduled_for_processing,const VideoFrame & video_frame)1460 void VideoStreamEncoder::OnFrame(Timestamp post_time,
1461 int frames_scheduled_for_processing,
1462 const VideoFrame& video_frame) {
1463 RTC_DCHECK_RUN_ON(&encoder_queue_);
1464 VideoFrame incoming_frame = video_frame;
1465
1466 // In some cases, e.g., when the frame from decoder is fed to encoder,
1467 // the timestamp may be set to the future. As the encoding pipeline assumes
1468 // capture time to be less than present time, we should reset the capture
1469 // timestamps here. Otherwise there may be issues with RTP send stream.
1470 if (incoming_frame.timestamp_us() > post_time.us())
1471 incoming_frame.set_timestamp_us(post_time.us());
1472
1473 // Capture time may come from clock with an offset and drift from clock_.
1474 int64_t capture_ntp_time_ms;
1475 if (video_frame.ntp_time_ms() > 0) {
1476 capture_ntp_time_ms = video_frame.ntp_time_ms();
1477 } else if (video_frame.render_time_ms() != 0) {
1478 capture_ntp_time_ms = video_frame.render_time_ms() + delta_ntp_internal_ms_;
1479 } else {
1480 capture_ntp_time_ms = post_time.ms() + delta_ntp_internal_ms_;
1481 }
1482 incoming_frame.set_ntp_time_ms(capture_ntp_time_ms);
1483
1484 // Convert NTP time, in ms, to RTP timestamp.
1485 const int kMsToRtpTimestamp = 90;
1486 incoming_frame.set_timestamp(
1487 kMsToRtpTimestamp * static_cast<uint32_t>(incoming_frame.ntp_time_ms()));
1488
1489 if (incoming_frame.ntp_time_ms() <= last_captured_timestamp_) {
1490 // We don't allow the same capture time for two frames, drop this one.
1491 RTC_LOG(LS_WARNING) << "Same/old NTP timestamp ("
1492 << incoming_frame.ntp_time_ms()
1493 << " <= " << last_captured_timestamp_
1494 << ") for incoming frame. Dropping.";
1495 encoder_queue_.PostTask([this, incoming_frame]() {
1496 RTC_DCHECK_RUN_ON(&encoder_queue_);
1497 accumulated_update_rect_.Union(incoming_frame.update_rect());
1498 accumulated_update_rect_is_valid_ &= incoming_frame.has_update_rect();
1499 });
1500 return;
1501 }
1502
1503 bool log_stats = false;
1504 if (post_time.ms() - last_frame_log_ms_ > kFrameLogIntervalMs) {
1505 last_frame_log_ms_ = post_time.ms();
1506 log_stats = true;
1507 }
1508
1509 last_captured_timestamp_ = incoming_frame.ntp_time_ms();
1510
1511 encoder_stats_observer_->OnIncomingFrame(incoming_frame.width(),
1512 incoming_frame.height());
1513 ++captured_frame_count_;
1514 CheckForAnimatedContent(incoming_frame, post_time.us());
1515 bool cwnd_frame_drop =
1516 cwnd_frame_drop_interval_ &&
1517 (cwnd_frame_counter_++ % cwnd_frame_drop_interval_.value() == 0);
1518 if (frames_scheduled_for_processing == 1 && !cwnd_frame_drop) {
1519 MaybeEncodeVideoFrame(incoming_frame, post_time.us());
1520 } else {
1521 if (cwnd_frame_drop) {
1522 // Frame drop by congestion window pushback. Do not encode this
1523 // frame.
1524 ++dropped_frame_cwnd_pushback_count_;
1525 encoder_stats_observer_->OnFrameDropped(
1526 VideoStreamEncoderObserver::DropReason::kCongestionWindow);
1527 } else {
1528 // There is a newer frame in flight. Do not encode this frame.
1529 RTC_LOG(LS_VERBOSE)
1530 << "Incoming frame dropped due to that the encoder is blocked.";
1531 ++dropped_frame_encoder_block_count_;
1532 encoder_stats_observer_->OnFrameDropped(
1533 VideoStreamEncoderObserver::DropReason::kEncoderQueue);
1534 }
1535 accumulated_update_rect_.Union(incoming_frame.update_rect());
1536 accumulated_update_rect_is_valid_ &= incoming_frame.has_update_rect();
1537 }
1538 if (log_stats) {
1539 RTC_LOG(LS_INFO) << "Number of frames: captured " << captured_frame_count_
1540 << ", dropped (due to congestion window pushback) "
1541 << dropped_frame_cwnd_pushback_count_
1542 << ", dropped (due to encoder blocked) "
1543 << dropped_frame_encoder_block_count_ << ", interval_ms "
1544 << kFrameLogIntervalMs;
1545 captured_frame_count_ = 0;
1546 dropped_frame_cwnd_pushback_count_ = 0;
1547 dropped_frame_encoder_block_count_ = 0;
1548 }
1549 }
1550
OnDiscardedFrame()1551 void VideoStreamEncoder::OnDiscardedFrame() {
1552 encoder_stats_observer_->OnFrameDropped(
1553 VideoStreamEncoderObserver::DropReason::kSource);
1554 }
1555
EncoderPaused() const1556 bool VideoStreamEncoder::EncoderPaused() const {
1557 RTC_DCHECK_RUN_ON(&encoder_queue_);
1558 // Pause video if paused by caller or as long as the network is down or the
1559 // pacer queue has grown too large in buffered mode.
1560 // If the pacer queue has grown too large or the network is down,
1561 // `last_encoder_rate_settings_->encoder_target` will be 0.
1562 return !last_encoder_rate_settings_ ||
1563 last_encoder_rate_settings_->encoder_target == DataRate::Zero();
1564 }
1565
TraceFrameDropStart()1566 void VideoStreamEncoder::TraceFrameDropStart() {
1567 RTC_DCHECK_RUN_ON(&encoder_queue_);
1568 // Start trace event only on the first frame after encoder is paused.
1569 if (!encoder_paused_and_dropped_frame_) {
1570 TRACE_EVENT_ASYNC_BEGIN0("webrtc", "EncoderPaused", this);
1571 }
1572 encoder_paused_and_dropped_frame_ = true;
1573 }
1574
TraceFrameDropEnd()1575 void VideoStreamEncoder::TraceFrameDropEnd() {
1576 RTC_DCHECK_RUN_ON(&encoder_queue_);
1577 // End trace event on first frame after encoder resumes, if frame was dropped.
1578 if (encoder_paused_and_dropped_frame_) {
1579 TRACE_EVENT_ASYNC_END0("webrtc", "EncoderPaused", this);
1580 }
1581 encoder_paused_and_dropped_frame_ = false;
1582 }
1583
1584 VideoStreamEncoder::EncoderRateSettings
UpdateBitrateAllocation(const EncoderRateSettings & rate_settings)1585 VideoStreamEncoder::UpdateBitrateAllocation(
1586 const EncoderRateSettings& rate_settings) {
1587 VideoBitrateAllocation new_allocation;
1588 // Only call allocators if bitrate > 0 (ie, not suspended), otherwise they
1589 // might cap the bitrate to the min bitrate configured.
1590 if (rate_allocator_ && rate_settings.encoder_target > DataRate::Zero()) {
1591 new_allocation = rate_allocator_->Allocate(VideoBitrateAllocationParameters(
1592 rate_settings.encoder_target, rate_settings.stable_encoder_target,
1593 rate_settings.rate_control.framerate_fps));
1594 }
1595
1596 EncoderRateSettings new_rate_settings = rate_settings;
1597 new_rate_settings.rate_control.target_bitrate = new_allocation;
1598 new_rate_settings.rate_control.bitrate = new_allocation;
1599 // VideoBitrateAllocator subclasses may allocate a bitrate higher than the
1600 // target in order to sustain the min bitrate of the video codec. In this
1601 // case, make sure the bandwidth allocation is at least equal the allocation
1602 // as that is part of the document contract for that field.
1603 new_rate_settings.rate_control.bandwidth_allocation =
1604 std::max(new_rate_settings.rate_control.bandwidth_allocation,
1605 DataRate::BitsPerSec(
1606 new_rate_settings.rate_control.bitrate.get_sum_bps()));
1607
1608 if (bitrate_adjuster_) {
1609 VideoBitrateAllocation adjusted_allocation =
1610 bitrate_adjuster_->AdjustRateAllocation(new_rate_settings.rate_control);
1611 RTC_LOG(LS_VERBOSE) << "Adjusting allocation, fps = "
1612 << rate_settings.rate_control.framerate_fps << ", from "
1613 << new_allocation.ToString() << ", to "
1614 << adjusted_allocation.ToString();
1615 new_rate_settings.rate_control.bitrate = adjusted_allocation;
1616 }
1617
1618 return new_rate_settings;
1619 }
1620
GetInputFramerateFps()1621 uint32_t VideoStreamEncoder::GetInputFramerateFps() {
1622 const uint32_t default_fps = max_framerate_ != -1 ? max_framerate_ : 30;
1623
1624 // This method may be called after we cleared out the frame_cadence_adapter_
1625 // reference in Stop(). In such a situation it's probably not important with a
1626 // decent estimate.
1627 absl::optional<uint32_t> input_fps =
1628 frame_cadence_adapter_ ? frame_cadence_adapter_->GetInputFrameRateFps()
1629 : absl::nullopt;
1630 if (!input_fps || *input_fps == 0) {
1631 return default_fps;
1632 }
1633 return *input_fps;
1634 }
1635
SetEncoderRates(const EncoderRateSettings & rate_settings)1636 void VideoStreamEncoder::SetEncoderRates(
1637 const EncoderRateSettings& rate_settings) {
1638 RTC_DCHECK_GT(rate_settings.rate_control.framerate_fps, 0.0);
1639 bool rate_control_changed =
1640 (!last_encoder_rate_settings_.has_value() ||
1641 last_encoder_rate_settings_->rate_control != rate_settings.rate_control);
1642 // For layer allocation signal we care only about the target bitrate (not the
1643 // adjusted one) and the target fps.
1644 bool layer_allocation_changed =
1645 !last_encoder_rate_settings_.has_value() ||
1646 last_encoder_rate_settings_->rate_control.target_bitrate !=
1647 rate_settings.rate_control.target_bitrate ||
1648 last_encoder_rate_settings_->rate_control.framerate_fps !=
1649 rate_settings.rate_control.framerate_fps;
1650
1651 if (last_encoder_rate_settings_ != rate_settings) {
1652 last_encoder_rate_settings_ = rate_settings;
1653 }
1654
1655 if (!encoder_)
1656 return;
1657
1658 // Make the cadence adapter know if streams were disabled.
1659 for (int spatial_index = 0;
1660 spatial_index != send_codec_.numberOfSimulcastStreams; ++spatial_index) {
1661 frame_cadence_adapter_->UpdateLayerStatus(
1662 spatial_index,
1663 /*enabled=*/rate_settings.rate_control.target_bitrate
1664 .GetSpatialLayerSum(spatial_index) > 0);
1665 }
1666
1667 // `bitrate_allocation` is 0 it means that the network is down or the send
1668 // pacer is full. We currently don't pass this on to the encoder since it is
1669 // unclear how current encoder implementations behave when given a zero target
1670 // bitrate.
1671 // TODO(perkj): Make sure all known encoder implementations handle zero
1672 // target bitrate and remove this check.
1673 if (rate_settings.rate_control.bitrate.get_sum_bps() == 0)
1674 return;
1675
1676 if (rate_control_changed) {
1677 encoder_->SetRates(rate_settings.rate_control);
1678
1679 encoder_stats_observer_->OnBitrateAllocationUpdated(
1680 send_codec_, rate_settings.rate_control.bitrate);
1681 frame_encode_metadata_writer_.OnSetRates(
1682 rate_settings.rate_control.bitrate,
1683 static_cast<uint32_t>(rate_settings.rate_control.framerate_fps + 0.5));
1684 stream_resource_manager_.SetEncoderRates(rate_settings.rate_control);
1685 if (layer_allocation_changed &&
1686 allocation_cb_type_ ==
1687 BitrateAllocationCallbackType::kVideoLayersAllocation) {
1688 sink_->OnVideoLayersAllocationUpdated(CreateVideoLayersAllocation(
1689 send_codec_, rate_settings.rate_control, encoder_->GetEncoderInfo()));
1690 }
1691 }
1692 if ((allocation_cb_type_ ==
1693 BitrateAllocationCallbackType::kVideoBitrateAllocation) ||
1694 (encoder_config_.content_type ==
1695 VideoEncoderConfig::ContentType::kScreen &&
1696 allocation_cb_type_ == BitrateAllocationCallbackType::
1697 kVideoBitrateAllocationWhenScreenSharing)) {
1698 sink_->OnBitrateAllocationUpdated(
1699 // Update allocation according to info from encoder. An encoder may
1700 // choose to not use all layers due to for example HW.
1701 UpdateAllocationFromEncoderInfo(
1702 rate_settings.rate_control.target_bitrate,
1703 encoder_->GetEncoderInfo()));
1704 }
1705 }
1706
MaybeEncodeVideoFrame(const VideoFrame & video_frame,int64_t time_when_posted_us)1707 void VideoStreamEncoder::MaybeEncodeVideoFrame(const VideoFrame& video_frame,
1708 int64_t time_when_posted_us) {
1709 RTC_DCHECK_RUN_ON(&encoder_queue_);
1710 input_state_provider_.OnFrameSizeObserved(video_frame.size());
1711
1712 if (!last_frame_info_ || video_frame.width() != last_frame_info_->width ||
1713 video_frame.height() != last_frame_info_->height ||
1714 video_frame.is_texture() != last_frame_info_->is_texture) {
1715 if ((!last_frame_info_ || video_frame.width() != last_frame_info_->width ||
1716 video_frame.height() != last_frame_info_->height) &&
1717 settings_.encoder_switch_request_callback && encoder_selector_) {
1718 if (auto encoder = encoder_selector_->OnResolutionChange(
1719 {video_frame.width(), video_frame.height()})) {
1720 settings_.encoder_switch_request_callback->RequestEncoderSwitch(
1721 *encoder, /*allow_default_fallback=*/false);
1722 }
1723 }
1724
1725 pending_encoder_reconfiguration_ = true;
1726 last_frame_info_ = VideoFrameInfo(video_frame.width(), video_frame.height(),
1727 video_frame.is_texture());
1728 RTC_LOG(LS_INFO) << "Video frame parameters changed: dimensions="
1729 << last_frame_info_->width << "x"
1730 << last_frame_info_->height
1731 << ", texture=" << last_frame_info_->is_texture << ".";
1732 // Force full frame update, since resolution has changed.
1733 accumulated_update_rect_ =
1734 VideoFrame::UpdateRect{0, 0, video_frame.width(), video_frame.height()};
1735 }
1736
1737 // We have to create the encoder before the frame drop logic,
1738 // because the latter depends on encoder_->GetScalingSettings.
1739 // According to the testcase
1740 // InitialFrameDropOffWhenEncoderDisabledScaling, the return value
1741 // from GetScalingSettings should enable or disable the frame drop.
1742
1743 // Update input frame rate before we start using it. If we update it after
1744 // any potential frame drop we are going to artificially increase frame sizes.
1745 // Poll the rate before updating, otherwise we risk the rate being estimated
1746 // a little too high at the start of the call when then window is small.
1747 uint32_t framerate_fps = GetInputFramerateFps();
1748 frame_cadence_adapter_->UpdateFrameRate();
1749
1750 int64_t now_ms = clock_->TimeInMilliseconds();
1751 if (pending_encoder_reconfiguration_) {
1752 ReconfigureEncoder();
1753 last_parameters_update_ms_.emplace(now_ms);
1754 } else if (!last_parameters_update_ms_ ||
1755 now_ms - *last_parameters_update_ms_ >=
1756 kParameterUpdateIntervalMs) {
1757 if (last_encoder_rate_settings_) {
1758 // Clone rate settings before update, so that SetEncoderRates() will
1759 // actually detect the change between the input and
1760 // `last_encoder_rate_setings_`, triggering the call to SetRate() on the
1761 // encoder.
1762 EncoderRateSettings new_rate_settings = *last_encoder_rate_settings_;
1763 new_rate_settings.rate_control.framerate_fps =
1764 static_cast<double>(framerate_fps);
1765 SetEncoderRates(UpdateBitrateAllocation(new_rate_settings));
1766 }
1767 last_parameters_update_ms_.emplace(now_ms);
1768 }
1769
1770 // Because pending frame will be dropped in any case, we need to
1771 // remember its updated region.
1772 if (pending_frame_) {
1773 encoder_stats_observer_->OnFrameDropped(
1774 VideoStreamEncoderObserver::DropReason::kEncoderQueue);
1775 accumulated_update_rect_.Union(pending_frame_->update_rect());
1776 accumulated_update_rect_is_valid_ &= pending_frame_->has_update_rect();
1777 }
1778
1779 if (DropDueToSize(video_frame.size())) {
1780 RTC_LOG(LS_INFO) << "Dropping frame. Too large for target bitrate.";
1781 stream_resource_manager_.OnFrameDroppedDueToSize();
1782 // Storing references to a native buffer risks blocking frame capture.
1783 if (video_frame.video_frame_buffer()->type() !=
1784 VideoFrameBuffer::Type::kNative) {
1785 pending_frame_ = video_frame;
1786 pending_frame_post_time_us_ = time_when_posted_us;
1787 } else {
1788 // Ensure that any previously stored frame is dropped.
1789 pending_frame_.reset();
1790 accumulated_update_rect_.Union(video_frame.update_rect());
1791 accumulated_update_rect_is_valid_ &= video_frame.has_update_rect();
1792 encoder_stats_observer_->OnFrameDropped(
1793 VideoStreamEncoderObserver::DropReason::kEncoderQueue);
1794 }
1795 return;
1796 }
1797 stream_resource_manager_.OnMaybeEncodeFrame();
1798
1799 if (EncoderPaused()) {
1800 // Storing references to a native buffer risks blocking frame capture.
1801 if (video_frame.video_frame_buffer()->type() !=
1802 VideoFrameBuffer::Type::kNative) {
1803 if (pending_frame_)
1804 TraceFrameDropStart();
1805 pending_frame_ = video_frame;
1806 pending_frame_post_time_us_ = time_when_posted_us;
1807 } else {
1808 // Ensure that any previously stored frame is dropped.
1809 pending_frame_.reset();
1810 TraceFrameDropStart();
1811 accumulated_update_rect_.Union(video_frame.update_rect());
1812 accumulated_update_rect_is_valid_ &= video_frame.has_update_rect();
1813 encoder_stats_observer_->OnFrameDropped(
1814 VideoStreamEncoderObserver::DropReason::kEncoderQueue);
1815 }
1816 return;
1817 }
1818
1819 pending_frame_.reset();
1820
1821 frame_dropper_.Leak(framerate_fps);
1822 // Frame dropping is enabled iff frame dropping is not force-disabled, and
1823 // rate controller is not trusted.
1824 const bool frame_dropping_enabled =
1825 !force_disable_frame_dropper_ &&
1826 !encoder_info_.has_trusted_rate_controller;
1827 frame_dropper_.Enable(frame_dropping_enabled);
1828 if (frame_dropping_enabled && frame_dropper_.DropFrame()) {
1829 RTC_LOG(LS_VERBOSE)
1830 << "Drop Frame: "
1831 "target bitrate "
1832 << (last_encoder_rate_settings_
1833 ? last_encoder_rate_settings_->encoder_target.bps()
1834 : 0)
1835 << ", input frame rate " << framerate_fps;
1836 OnDroppedFrame(
1837 EncodedImageCallback::DropReason::kDroppedByMediaOptimizations);
1838 accumulated_update_rect_.Union(video_frame.update_rect());
1839 accumulated_update_rect_is_valid_ &= video_frame.has_update_rect();
1840 return;
1841 }
1842
1843 EncodeVideoFrame(video_frame, time_when_posted_us);
1844 }
1845
EncodeVideoFrame(const VideoFrame & video_frame,int64_t time_when_posted_us)1846 void VideoStreamEncoder::EncodeVideoFrame(const VideoFrame& video_frame,
1847 int64_t time_when_posted_us) {
1848 RTC_DCHECK_RUN_ON(&encoder_queue_);
1849 RTC_LOG(LS_VERBOSE) << __func__ << " posted " << time_when_posted_us
1850 << " ntp time " << video_frame.ntp_time_ms();
1851
1852 // If the encoder fail we can't continue to encode frames. When this happens
1853 // the WebrtcVideoSender is notified and the whole VideoSendStream is
1854 // recreated.
1855 if (encoder_failed_ || !encoder_initialized_)
1856 return;
1857
1858 // It's possible that EncodeVideoFrame can be called after we've completed
1859 // a Stop() operation. Check if the encoder_ is set before continuing.
1860 // See: bugs.webrtc.org/12857
1861 if (!encoder_)
1862 return;
1863
1864 TraceFrameDropEnd();
1865
1866 // Encoder metadata needs to be updated before encode complete callback.
1867 VideoEncoder::EncoderInfo info = encoder_->GetEncoderInfo();
1868 if (info.implementation_name != encoder_info_.implementation_name ||
1869 info.is_hardware_accelerated != encoder_info_.is_hardware_accelerated) {
1870 encoder_stats_observer_->OnEncoderImplementationChanged({
1871 .name = info.implementation_name,
1872 .is_hardware_accelerated = info.is_hardware_accelerated,
1873 });
1874 if (bitrate_adjuster_) {
1875 // Encoder implementation changed, reset overshoot detector states.
1876 bitrate_adjuster_->Reset();
1877 }
1878 }
1879
1880 if (encoder_info_ != info) {
1881 OnEncoderSettingsChanged();
1882 stream_resource_manager_.ConfigureEncodeUsageResource();
1883 // Re-configure scalers when encoder info changed. Consider two cases:
1884 // 1. When the status of the scaler changes from enabled to disabled, if we
1885 // don't do this CL, scaler will adapt up/down to trigger an unnecessary
1886 // full ReconfigureEncoder() when the scaler should be banned.
1887 // 2. When the status of the scaler changes from disabled to enabled, if we
1888 // don't do this CL, scaler will not work until some code trigger
1889 // ReconfigureEncoder(). In extreme cases, the scaler doesn't even work for
1890 // a long time when we expect that the scaler should work.
1891 stream_resource_manager_.ConfigureQualityScaler(info);
1892 stream_resource_manager_.ConfigureBandwidthQualityScaler(info);
1893
1894 RTC_LOG(LS_INFO) << "Encoder info changed to " << info.ToString();
1895 }
1896
1897 if (bitrate_adjuster_) {
1898 for (size_t si = 0; si < kMaxSpatialLayers; ++si) {
1899 if (info.fps_allocation[si] != encoder_info_.fps_allocation[si]) {
1900 bitrate_adjuster_->OnEncoderInfo(info);
1901 break;
1902 }
1903 }
1904 }
1905 encoder_info_ = info;
1906 last_encode_info_ms_ = clock_->TimeInMilliseconds();
1907
1908 VideoFrame out_frame(video_frame);
1909 // Crop or scale the frame if needed. Dimension may be reduced to fit encoder
1910 // requirements, e.g. some encoders may require them to be divisible by 4.
1911 if ((crop_width_ > 0 || crop_height_ > 0) &&
1912 (out_frame.video_frame_buffer()->type() !=
1913 VideoFrameBuffer::Type::kNative ||
1914 !info.supports_native_handle)) {
1915 int cropped_width = video_frame.width() - crop_width_;
1916 int cropped_height = video_frame.height() - crop_height_;
1917 rtc::scoped_refptr<VideoFrameBuffer> cropped_buffer;
1918 // TODO(ilnik): Remove scaling if cropping is too big, as it should never
1919 // happen after SinkWants signaled correctly from ReconfigureEncoder.
1920 VideoFrame::UpdateRect update_rect = video_frame.update_rect();
1921 if (crop_width_ < 4 && crop_height_ < 4) {
1922 // The difference is small, crop without scaling.
1923 cropped_buffer = video_frame.video_frame_buffer()->CropAndScale(
1924 crop_width_ / 2, crop_height_ / 2, cropped_width, cropped_height,
1925 cropped_width, cropped_height);
1926 update_rect.offset_x -= crop_width_ / 2;
1927 update_rect.offset_y -= crop_height_ / 2;
1928 update_rect.Intersect(
1929 VideoFrame::UpdateRect{0, 0, cropped_width, cropped_height});
1930
1931 } else {
1932 // The difference is large, scale it.
1933 cropped_buffer = video_frame.video_frame_buffer()->Scale(cropped_width,
1934 cropped_height);
1935 if (!update_rect.IsEmpty()) {
1936 // Since we can't reason about pixels after scaling, we invalidate whole
1937 // picture, if anything changed.
1938 update_rect =
1939 VideoFrame::UpdateRect{0, 0, cropped_width, cropped_height};
1940 }
1941 }
1942 if (!cropped_buffer) {
1943 RTC_LOG(LS_ERROR) << "Cropping and scaling frame failed, dropping frame.";
1944 return;
1945 }
1946
1947 out_frame.set_video_frame_buffer(cropped_buffer);
1948 out_frame.set_update_rect(update_rect);
1949 out_frame.set_ntp_time_ms(video_frame.ntp_time_ms());
1950 // Since accumulated_update_rect_ is constructed before cropping,
1951 // we can't trust it. If any changes were pending, we invalidate whole
1952 // frame here.
1953 if (!accumulated_update_rect_.IsEmpty()) {
1954 accumulated_update_rect_ =
1955 VideoFrame::UpdateRect{0, 0, out_frame.width(), out_frame.height()};
1956 accumulated_update_rect_is_valid_ = false;
1957 }
1958 }
1959
1960 if (!accumulated_update_rect_is_valid_) {
1961 out_frame.clear_update_rect();
1962 } else if (!accumulated_update_rect_.IsEmpty() &&
1963 out_frame.has_update_rect()) {
1964 accumulated_update_rect_.Union(out_frame.update_rect());
1965 accumulated_update_rect_.Intersect(
1966 VideoFrame::UpdateRect{0, 0, out_frame.width(), out_frame.height()});
1967 out_frame.set_update_rect(accumulated_update_rect_);
1968 accumulated_update_rect_.MakeEmptyUpdate();
1969 }
1970 accumulated_update_rect_is_valid_ = true;
1971
1972 TRACE_EVENT_ASYNC_STEP0("webrtc", "Video", video_frame.render_time_ms(),
1973 "Encode");
1974
1975 stream_resource_manager_.OnEncodeStarted(out_frame, time_when_posted_us);
1976
1977 // The encoder should get the size that it expects.
1978 RTC_DCHECK(send_codec_.width <= out_frame.width() &&
1979 send_codec_.height <= out_frame.height())
1980 << "Encoder configured to " << send_codec_.width << "x"
1981 << send_codec_.height << " received a too small frame "
1982 << out_frame.width() << "x" << out_frame.height();
1983
1984 TRACE_EVENT1("webrtc", "VCMGenericEncoder::Encode", "timestamp",
1985 out_frame.timestamp());
1986
1987 frame_encode_metadata_writer_.OnEncodeStarted(out_frame);
1988
1989 const int32_t encode_status = encoder_->Encode(out_frame, &next_frame_types_);
1990 was_encode_called_since_last_initialization_ = true;
1991
1992 if (encode_status < 0) {
1993 RTC_LOG(LS_ERROR) << "Encoder failed, failing encoder format: "
1994 << encoder_config_.video_format.ToString();
1995 RequestEncoderSwitch();
1996 return;
1997 }
1998
1999 for (auto& it : next_frame_types_) {
2000 it = VideoFrameType::kVideoFrameDelta;
2001 }
2002 }
2003
RequestRefreshFrame()2004 void VideoStreamEncoder::RequestRefreshFrame() {
2005 worker_queue_->PostTask(SafeTask(task_safety_.flag(), [this] {
2006 RTC_DCHECK_RUN_ON(worker_queue_);
2007 video_source_sink_controller_.RequestRefreshFrame();
2008 }));
2009 }
2010
SendKeyFrame(const std::vector<VideoFrameType> & layers)2011 void VideoStreamEncoder::SendKeyFrame(
2012 const std::vector<VideoFrameType>& layers) {
2013 if (!encoder_queue_.IsCurrent()) {
2014 encoder_queue_.PostTask([this, layers] { SendKeyFrame(layers); });
2015 return;
2016 }
2017 RTC_DCHECK_RUN_ON(&encoder_queue_);
2018 TRACE_EVENT0("webrtc", "OnKeyFrameRequest");
2019 RTC_DCHECK(!next_frame_types_.empty());
2020
2021 if (frame_cadence_adapter_)
2022 frame_cadence_adapter_->ProcessKeyFrameRequest();
2023
2024 if (!encoder_) {
2025 RTC_DLOG(LS_INFO) << __func__ << " no encoder.";
2026 return; // Shutting down, or not configured yet.
2027 }
2028
2029 if (!layers.empty()) {
2030 RTC_DCHECK_EQ(layers.size(), next_frame_types_.size());
2031 for (size_t i = 0; i < layers.size() && i < next_frame_types_.size(); i++) {
2032 next_frame_types_[i] = layers[i];
2033 }
2034 } else {
2035 std::fill(next_frame_types_.begin(), next_frame_types_.end(),
2036 VideoFrameType::kVideoFrameKey);
2037 }
2038 }
2039
OnLossNotification(const VideoEncoder::LossNotification & loss_notification)2040 void VideoStreamEncoder::OnLossNotification(
2041 const VideoEncoder::LossNotification& loss_notification) {
2042 if (!encoder_queue_.IsCurrent()) {
2043 encoder_queue_.PostTask(
2044 [this, loss_notification] { OnLossNotification(loss_notification); });
2045 return;
2046 }
2047
2048 RTC_DCHECK_RUN_ON(&encoder_queue_);
2049 if (encoder_) {
2050 encoder_->OnLossNotification(loss_notification);
2051 }
2052 }
2053
AugmentEncodedImage(const EncodedImage & encoded_image,const CodecSpecificInfo * codec_specific_info)2054 EncodedImage VideoStreamEncoder::AugmentEncodedImage(
2055 const EncodedImage& encoded_image,
2056 const CodecSpecificInfo* codec_specific_info) {
2057 EncodedImage image_copy(encoded_image);
2058 const size_t spatial_idx = encoded_image.SpatialIndex().value_or(0);
2059 frame_encode_metadata_writer_.FillTimingInfo(spatial_idx, &image_copy);
2060 frame_encode_metadata_writer_.UpdateBitstream(codec_specific_info,
2061 &image_copy);
2062 VideoCodecType codec_type = codec_specific_info
2063 ? codec_specific_info->codecType
2064 : VideoCodecType::kVideoCodecGeneric;
2065 if (image_copy.qp_ < 0 && qp_parsing_allowed_) {
2066 // Parse encoded frame QP if that was not provided by encoder.
2067 image_copy.qp_ = qp_parser_
2068 .Parse(codec_type, spatial_idx, image_copy.data(),
2069 image_copy.size())
2070 .value_or(-1);
2071 }
2072 RTC_LOG(LS_VERBOSE) << __func__ << " spatial_idx " << spatial_idx << " qp "
2073 << image_copy.qp_;
2074 image_copy.SetAtTargetQuality(codec_type == kVideoCodecVP8 &&
2075 image_copy.qp_ <= kVp8SteadyStateQpThreshold);
2076
2077 // Piggyback ALR experiment group id and simulcast id into the content type.
2078 const uint8_t experiment_id =
2079 experiment_groups_[videocontenttypehelpers::IsScreenshare(
2080 image_copy.content_type_)];
2081
2082 // TODO(ilnik): This will force content type extension to be present even
2083 // for realtime video. At the expense of miniscule overhead we will get
2084 // sliced receive statistics.
2085 RTC_CHECK(videocontenttypehelpers::SetExperimentId(&image_copy.content_type_,
2086 experiment_id));
2087 // We count simulcast streams from 1 on the wire. That's why we set simulcast
2088 // id in content type to +1 of that is actual simulcast index. This is because
2089 // value 0 on the wire is reserved for 'no simulcast stream specified'.
2090 RTC_CHECK(videocontenttypehelpers::SetSimulcastId(
2091 &image_copy.content_type_, static_cast<uint8_t>(spatial_idx + 1)));
2092
2093 return image_copy;
2094 }
2095
OnEncodedImage(const EncodedImage & encoded_image,const CodecSpecificInfo * codec_specific_info)2096 EncodedImageCallback::Result VideoStreamEncoder::OnEncodedImage(
2097 const EncodedImage& encoded_image,
2098 const CodecSpecificInfo* codec_specific_info) {
2099 TRACE_EVENT_INSTANT1("webrtc", "VCMEncodedFrameCallback::Encoded",
2100 "timestamp", encoded_image.Timestamp());
2101
2102 // TODO(bugs.webrtc.org/10520): Signal the simulcast id explicitly.
2103
2104 const size_t spatial_idx = encoded_image.SpatialIndex().value_or(0);
2105 const VideoCodecType codec_type = codec_specific_info
2106 ? codec_specific_info->codecType
2107 : VideoCodecType::kVideoCodecGeneric;
2108 EncodedImage image_copy =
2109 AugmentEncodedImage(encoded_image, codec_specific_info);
2110
2111 // Post a task because `send_codec_` requires `encoder_queue_` lock and we
2112 // need to update on quality convergence.
2113 unsigned int image_width = image_copy._encodedWidth;
2114 unsigned int image_height = image_copy._encodedHeight;
2115 encoder_queue_.PostTask([this, codec_type, image_width, image_height,
2116 spatial_idx,
2117 at_target_quality = image_copy.IsAtTargetQuality()] {
2118 RTC_DCHECK_RUN_ON(&encoder_queue_);
2119
2120 // Let the frame cadence adapter know about quality convergence.
2121 if (frame_cadence_adapter_)
2122 frame_cadence_adapter_->UpdateLayerQualityConvergence(spatial_idx,
2123 at_target_quality);
2124
2125 // Currently, the internal quality scaler is used for VP9 instead of the
2126 // webrtc qp scaler (in the no-svc case or if only a single spatial layer is
2127 // encoded). It has to be explicitly detected and reported to adaptation
2128 // metrics.
2129 if (codec_type == VideoCodecType::kVideoCodecVP9 &&
2130 send_codec_.VP9()->automaticResizeOn) {
2131 unsigned int expected_width = send_codec_.width;
2132 unsigned int expected_height = send_codec_.height;
2133 int num_active_layers = 0;
2134 for (int i = 0; i < send_codec_.VP9()->numberOfSpatialLayers; ++i) {
2135 if (send_codec_.spatialLayers[i].active) {
2136 ++num_active_layers;
2137 expected_width = send_codec_.spatialLayers[i].width;
2138 expected_height = send_codec_.spatialLayers[i].height;
2139 }
2140 }
2141 RTC_DCHECK_LE(num_active_layers, 1)
2142 << "VP9 quality scaling is enabled for "
2143 "SVC with several active layers.";
2144 encoder_stats_observer_->OnEncoderInternalScalerUpdate(
2145 image_width < expected_width || image_height < expected_height);
2146 }
2147 });
2148
2149 // Encoded is called on whatever thread the real encoder implementation run
2150 // on. In the case of hardware encoders, there might be several encoders
2151 // running in parallel on different threads.
2152 encoder_stats_observer_->OnSendEncodedImage(image_copy, codec_specific_info);
2153
2154 EncodedImageCallback::Result result =
2155 sink_->OnEncodedImage(image_copy, codec_specific_info);
2156
2157 // We are only interested in propagating the meta-data about the image, not
2158 // encoded data itself, to the post encode function. Since we cannot be sure
2159 // the pointer will still be valid when run on the task queue, set it to null.
2160 DataSize frame_size = DataSize::Bytes(image_copy.size());
2161 image_copy.ClearEncodedData();
2162
2163 int temporal_index = 0;
2164 if (codec_specific_info) {
2165 if (codec_specific_info->codecType == kVideoCodecVP9) {
2166 temporal_index = codec_specific_info->codecSpecific.VP9.temporal_idx;
2167 } else if (codec_specific_info->codecType == kVideoCodecVP8) {
2168 temporal_index = codec_specific_info->codecSpecific.VP8.temporalIdx;
2169 }
2170 }
2171 if (temporal_index == kNoTemporalIdx) {
2172 temporal_index = 0;
2173 }
2174
2175 RunPostEncode(image_copy, clock_->CurrentTime().us(), temporal_index,
2176 frame_size);
2177
2178 if (result.error == Result::OK) {
2179 // In case of an internal encoder running on a separate thread, the
2180 // decision to drop a frame might be a frame late and signaled via
2181 // atomic flag. This is because we can't easily wait for the worker thread
2182 // without risking deadlocks, eg during shutdown when the worker thread
2183 // might be waiting for the internal encoder threads to stop.
2184 if (pending_frame_drops_.load() > 0) {
2185 int pending_drops = pending_frame_drops_.fetch_sub(1);
2186 RTC_DCHECK_GT(pending_drops, 0);
2187 result.drop_next_frame = true;
2188 }
2189 }
2190
2191 return result;
2192 }
2193
OnDroppedFrame(DropReason reason)2194 void VideoStreamEncoder::OnDroppedFrame(DropReason reason) {
2195 switch (reason) {
2196 case DropReason::kDroppedByMediaOptimizations:
2197 encoder_stats_observer_->OnFrameDropped(
2198 VideoStreamEncoderObserver::DropReason::kMediaOptimization);
2199 break;
2200 case DropReason::kDroppedByEncoder:
2201 encoder_stats_observer_->OnFrameDropped(
2202 VideoStreamEncoderObserver::DropReason::kEncoder);
2203 break;
2204 }
2205 sink_->OnDroppedFrame(reason);
2206 encoder_queue_.PostTask([this, reason] {
2207 RTC_DCHECK_RUN_ON(&encoder_queue_);
2208 stream_resource_manager_.OnFrameDropped(reason);
2209 });
2210 }
2211
UpdateTargetBitrate(DataRate target_bitrate,double cwnd_reduce_ratio)2212 DataRate VideoStreamEncoder::UpdateTargetBitrate(DataRate target_bitrate,
2213 double cwnd_reduce_ratio) {
2214 RTC_DCHECK_RUN_ON(&encoder_queue_);
2215 DataRate updated_target_bitrate = target_bitrate;
2216
2217 // Drop frames when congestion window pushback ratio is larger than 1
2218 // percent and target bitrate is larger than codec min bitrate.
2219 // When target_bitrate is 0 means codec is paused, skip frame dropping.
2220 if (cwnd_reduce_ratio > 0.01 && target_bitrate.bps() > 0 &&
2221 target_bitrate.bps() > send_codec_.minBitrate * 1000) {
2222 int reduce_bitrate_bps = std::min(
2223 static_cast<int>(target_bitrate.bps() * cwnd_reduce_ratio),
2224 static_cast<int>(target_bitrate.bps() - send_codec_.minBitrate * 1000));
2225 if (reduce_bitrate_bps > 0) {
2226 // At maximum the congestion window can drop 1/2 frames.
2227 cwnd_frame_drop_interval_ = std::max(
2228 2, static_cast<int>(target_bitrate.bps() / reduce_bitrate_bps));
2229 // Reduce target bitrate accordingly.
2230 updated_target_bitrate =
2231 target_bitrate - (target_bitrate / cwnd_frame_drop_interval_.value());
2232 return updated_target_bitrate;
2233 }
2234 }
2235 cwnd_frame_drop_interval_.reset();
2236 return updated_target_bitrate;
2237 }
2238
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)2239 void VideoStreamEncoder::OnBitrateUpdated(DataRate target_bitrate,
2240 DataRate stable_target_bitrate,
2241 DataRate link_allocation,
2242 uint8_t fraction_lost,
2243 int64_t round_trip_time_ms,
2244 double cwnd_reduce_ratio) {
2245 RTC_DCHECK_GE(link_allocation, target_bitrate);
2246 if (!encoder_queue_.IsCurrent()) {
2247 encoder_queue_.PostTask([this, target_bitrate, stable_target_bitrate,
2248 link_allocation, fraction_lost, round_trip_time_ms,
2249 cwnd_reduce_ratio] {
2250 DataRate updated_target_bitrate =
2251 UpdateTargetBitrate(target_bitrate, cwnd_reduce_ratio);
2252 OnBitrateUpdated(updated_target_bitrate, stable_target_bitrate,
2253 link_allocation, fraction_lost, round_trip_time_ms,
2254 cwnd_reduce_ratio);
2255 });
2256 return;
2257 }
2258 RTC_DCHECK_RUN_ON(&encoder_queue_);
2259
2260 const bool video_is_suspended = target_bitrate == DataRate::Zero();
2261 const bool video_suspension_changed = video_is_suspended != EncoderPaused();
2262
2263 if (!video_is_suspended && settings_.encoder_switch_request_callback &&
2264 encoder_selector_) {
2265 if (auto encoder = encoder_selector_->OnAvailableBitrate(link_allocation)) {
2266 settings_.encoder_switch_request_callback->RequestEncoderSwitch(
2267 *encoder, /*allow_default_fallback=*/false);
2268 }
2269 }
2270
2271 RTC_DCHECK(sink_) << "sink_ must be set before the encoder is active.";
2272
2273 RTC_LOG(LS_VERBOSE) << "OnBitrateUpdated, bitrate " << target_bitrate.bps()
2274 << " stable bitrate = " << stable_target_bitrate.bps()
2275 << " link allocation bitrate = " << link_allocation.bps()
2276 << " packet loss " << static_cast<int>(fraction_lost)
2277 << " rtt " << round_trip_time_ms;
2278
2279 if (encoder_) {
2280 encoder_->OnPacketLossRateUpdate(static_cast<float>(fraction_lost) / 256.f);
2281 encoder_->OnRttUpdate(round_trip_time_ms);
2282 }
2283
2284 uint32_t framerate_fps = GetInputFramerateFps();
2285 frame_dropper_.SetRates((target_bitrate.bps() + 500) / 1000, framerate_fps);
2286
2287 EncoderRateSettings new_rate_settings{
2288 VideoBitrateAllocation(), static_cast<double>(framerate_fps),
2289 link_allocation, target_bitrate, stable_target_bitrate};
2290 SetEncoderRates(UpdateBitrateAllocation(new_rate_settings));
2291
2292 if (target_bitrate.bps() != 0)
2293 encoder_target_bitrate_bps_ = target_bitrate.bps();
2294
2295 stream_resource_manager_.SetTargetBitrate(target_bitrate);
2296
2297 if (video_suspension_changed) {
2298 RTC_LOG(LS_INFO) << "Video suspend state changed to: "
2299 << (video_is_suspended ? "suspended" : "not suspended");
2300 encoder_stats_observer_->OnSuspendChange(video_is_suspended);
2301
2302 if (!video_is_suspended && pending_frame_ &&
2303 !DropDueToSize(pending_frame_->size())) {
2304 // A pending stored frame can be processed.
2305 int64_t pending_time_us =
2306 clock_->CurrentTime().us() - pending_frame_post_time_us_;
2307 if (pending_time_us < kPendingFrameTimeoutMs * 1000)
2308 EncodeVideoFrame(*pending_frame_, pending_frame_post_time_us_);
2309 pending_frame_.reset();
2310 } else if (!video_is_suspended && !pending_frame_ &&
2311 encoder_paused_and_dropped_frame_) {
2312 // A frame was enqueued during pause-state, but since it was a native
2313 // frame we could not store it in `pending_frame_` so request a
2314 // refresh-frame instead.
2315 RequestRefreshFrame();
2316 }
2317 }
2318 }
2319
DropDueToSize(uint32_t pixel_count) const2320 bool VideoStreamEncoder::DropDueToSize(uint32_t pixel_count) const {
2321 if (!encoder_ || !stream_resource_manager_.DropInitialFrames() ||
2322 !encoder_target_bitrate_bps_.has_value()) {
2323 return false;
2324 }
2325
2326 bool simulcast_or_svc =
2327 (send_codec_.codecType == VideoCodecType::kVideoCodecVP9 &&
2328 send_codec_.VP9().numberOfSpatialLayers > 1) ||
2329 (send_codec_.numberOfSimulcastStreams > 1 ||
2330 encoder_config_.simulcast_layers.size() > 1);
2331
2332 if (simulcast_or_svc) {
2333 if (stream_resource_manager_.SingleActiveStreamPixels()) {
2334 pixel_count = stream_resource_manager_.SingleActiveStreamPixels().value();
2335 } else {
2336 return false;
2337 }
2338 }
2339
2340 uint32_t bitrate_bps =
2341 stream_resource_manager_.UseBandwidthAllocationBps().value_or(
2342 encoder_target_bitrate_bps_.value());
2343
2344 absl::optional<VideoEncoder::ResolutionBitrateLimits> encoder_bitrate_limits =
2345 GetEncoderInfoWithBitrateLimitUpdate(
2346 encoder_->GetEncoderInfo(), encoder_config_, default_limits_allowed_)
2347 .GetEncoderBitrateLimitsForResolution(pixel_count);
2348
2349 if (encoder_bitrate_limits.has_value()) {
2350 // Use bitrate limits provided by encoder.
2351 return bitrate_bps <
2352 static_cast<uint32_t>(encoder_bitrate_limits->min_start_bitrate_bps);
2353 }
2354
2355 if (bitrate_bps < 300000 /* qvga */) {
2356 return pixel_count > 320 * 240;
2357 } else if (bitrate_bps < 500000 /* vga */) {
2358 return pixel_count > 640 * 480;
2359 }
2360 return false;
2361 }
2362
OnVideoSourceRestrictionsUpdated(VideoSourceRestrictions restrictions,const VideoAdaptationCounters & adaptation_counters,rtc::scoped_refptr<Resource> reason,const VideoSourceRestrictions & unfiltered_restrictions)2363 void VideoStreamEncoder::OnVideoSourceRestrictionsUpdated(
2364 VideoSourceRestrictions restrictions,
2365 const VideoAdaptationCounters& adaptation_counters,
2366 rtc::scoped_refptr<Resource> reason,
2367 const VideoSourceRestrictions& unfiltered_restrictions) {
2368 RTC_DCHECK_RUN_ON(&encoder_queue_);
2369 RTC_LOG(LS_INFO) << "Updating sink restrictions from "
2370 << (reason ? reason->Name() : std::string("<null>"))
2371 << " to " << restrictions.ToString();
2372
2373 // TODO(webrtc:14451) Split video_source_sink_controller_
2374 // so that ownership on restrictions/wants is kept on &encoder_queue_
2375 latest_restrictions_ = restrictions;
2376
2377 worker_queue_->PostTask(SafeTask(
2378 task_safety_.flag(), [this, restrictions = std::move(restrictions)]() {
2379 RTC_DCHECK_RUN_ON(worker_queue_);
2380 video_source_sink_controller_.SetRestrictions(std::move(restrictions));
2381 video_source_sink_controller_.PushSourceSinkSettings();
2382 }));
2383 }
2384
RunPostEncode(const EncodedImage & encoded_image,int64_t time_sent_us,int temporal_index,DataSize frame_size)2385 void VideoStreamEncoder::RunPostEncode(const EncodedImage& encoded_image,
2386 int64_t time_sent_us,
2387 int temporal_index,
2388 DataSize frame_size) {
2389 if (!encoder_queue_.IsCurrent()) {
2390 encoder_queue_.PostTask([this, encoded_image, time_sent_us, temporal_index,
2391 frame_size] {
2392 RunPostEncode(encoded_image, time_sent_us, temporal_index, frame_size);
2393 });
2394 return;
2395 }
2396
2397 RTC_DCHECK_RUN_ON(&encoder_queue_);
2398
2399 absl::optional<int> encode_duration_us;
2400 if (encoded_image.timing_.flags != VideoSendTiming::kInvalid) {
2401 encode_duration_us =
2402 TimeDelta::Millis(encoded_image.timing_.encode_finish_ms -
2403 encoded_image.timing_.encode_start_ms)
2404 .us();
2405 }
2406
2407 // Run post encode tasks, such as overuse detection and frame rate/drop
2408 // stats for internal encoders.
2409 const bool keyframe =
2410 encoded_image._frameType == VideoFrameType::kVideoFrameKey;
2411
2412 if (!frame_size.IsZero()) {
2413 frame_dropper_.Fill(frame_size.bytes(), !keyframe);
2414 }
2415
2416 stream_resource_manager_.OnEncodeCompleted(encoded_image, time_sent_us,
2417 encode_duration_us, frame_size);
2418 if (bitrate_adjuster_) {
2419 bitrate_adjuster_->OnEncodedFrame(
2420 frame_size, encoded_image.SpatialIndex().value_or(0), temporal_index);
2421 }
2422 }
2423
ReleaseEncoder()2424 void VideoStreamEncoder::ReleaseEncoder() {
2425 if (!encoder_ || !encoder_initialized_) {
2426 return;
2427 }
2428 encoder_->Release();
2429 encoder_initialized_ = false;
2430 TRACE_EVENT0("webrtc", "VCMGenericEncoder::Release");
2431 }
2432
2433 VideoStreamEncoder::AutomaticAnimationDetectionExperiment
ParseAutomatincAnimationDetectionFieldTrial() const2434 VideoStreamEncoder::ParseAutomatincAnimationDetectionFieldTrial() const {
2435 AutomaticAnimationDetectionExperiment result;
2436
2437 result.Parser()->Parse(
2438 field_trials_.Lookup("WebRTC-AutomaticAnimationDetectionScreenshare"));
2439
2440 if (!result.enabled) {
2441 RTC_LOG(LS_INFO) << "Automatic animation detection experiment is disabled.";
2442 return result;
2443 }
2444
2445 RTC_LOG(LS_INFO) << "Automatic animation detection experiment settings:"
2446 " min_duration_ms="
2447 << result.min_duration_ms
2448 << " min_area_ration=" << result.min_area_ratio
2449 << " min_fps=" << result.min_fps;
2450
2451 return result;
2452 }
2453
CheckForAnimatedContent(const VideoFrame & frame,int64_t time_when_posted_in_us)2454 void VideoStreamEncoder::CheckForAnimatedContent(
2455 const VideoFrame& frame,
2456 int64_t time_when_posted_in_us) {
2457 if (!automatic_animation_detection_experiment_.enabled ||
2458 encoder_config_.content_type !=
2459 VideoEncoderConfig::ContentType::kScreen ||
2460 stream_resource_manager_.degradation_preference() !=
2461 DegradationPreference::BALANCED) {
2462 return;
2463 }
2464
2465 if (expect_resize_state_ == ExpectResizeState::kResize && last_frame_info_ &&
2466 last_frame_info_->width != frame.width() &&
2467 last_frame_info_->height != frame.height()) {
2468 // On applying resolution cap there will be one frame with no/different
2469 // update, which should be skipped.
2470 // It can be delayed by several frames.
2471 expect_resize_state_ = ExpectResizeState::kFirstFrameAfterResize;
2472 return;
2473 }
2474
2475 if (expect_resize_state_ == ExpectResizeState::kFirstFrameAfterResize) {
2476 // The first frame after resize should have new, scaled update_rect.
2477 if (frame.has_update_rect()) {
2478 last_update_rect_ = frame.update_rect();
2479 } else {
2480 last_update_rect_ = absl::nullopt;
2481 }
2482 expect_resize_state_ = ExpectResizeState::kNoResize;
2483 }
2484
2485 bool should_cap_resolution = false;
2486 if (!frame.has_update_rect()) {
2487 last_update_rect_ = absl::nullopt;
2488 animation_start_time_ = Timestamp::PlusInfinity();
2489 } else if ((!last_update_rect_ ||
2490 frame.update_rect() != *last_update_rect_)) {
2491 last_update_rect_ = frame.update_rect();
2492 animation_start_time_ = Timestamp::Micros(time_when_posted_in_us);
2493 } else {
2494 TimeDelta animation_duration =
2495 Timestamp::Micros(time_when_posted_in_us) - animation_start_time_;
2496 float area_ratio = static_cast<float>(last_update_rect_->width *
2497 last_update_rect_->height) /
2498 (frame.width() * frame.height());
2499 if (animation_duration.ms() >=
2500 automatic_animation_detection_experiment_.min_duration_ms &&
2501 area_ratio >=
2502 automatic_animation_detection_experiment_.min_area_ratio &&
2503 encoder_stats_observer_->GetInputFrameRate() >=
2504 automatic_animation_detection_experiment_.min_fps) {
2505 should_cap_resolution = true;
2506 }
2507 }
2508 if (cap_resolution_due_to_video_content_ != should_cap_resolution) {
2509 expect_resize_state_ = should_cap_resolution ? ExpectResizeState::kResize
2510 : ExpectResizeState::kNoResize;
2511 cap_resolution_due_to_video_content_ = should_cap_resolution;
2512 if (should_cap_resolution) {
2513 RTC_LOG(LS_INFO) << "Applying resolution cap due to animation detection.";
2514 } else {
2515 RTC_LOG(LS_INFO) << "Removing resolution cap due to no consistent "
2516 "animation detection.";
2517 }
2518 // TODO(webrtc:14451) Split video_source_sink_controller_
2519 // so that ownership on restrictions/wants is kept on &encoder_queue_
2520 if (should_cap_resolution) {
2521 animate_restrictions_ =
2522 VideoSourceRestrictions(kMaxAnimationPixels,
2523 /* target_pixels_per_frame= */ absl::nullopt,
2524 /* max_frame_rate= */ absl::nullopt);
2525 } else {
2526 animate_restrictions_.reset();
2527 }
2528
2529 worker_queue_->PostTask(
2530 SafeTask(task_safety_.flag(), [this, should_cap_resolution]() {
2531 RTC_DCHECK_RUN_ON(worker_queue_);
2532 video_source_sink_controller_.SetPixelsPerFrameUpperLimit(
2533 should_cap_resolution
2534 ? absl::optional<size_t>(kMaxAnimationPixels)
2535 : absl::nullopt);
2536 video_source_sink_controller_.PushSourceSinkSettings();
2537 }));
2538 }
2539 }
2540
InjectAdaptationResource(rtc::scoped_refptr<Resource> resource,VideoAdaptationReason reason)2541 void VideoStreamEncoder::InjectAdaptationResource(
2542 rtc::scoped_refptr<Resource> resource,
2543 VideoAdaptationReason reason) {
2544 encoder_queue_.PostTask([this, resource = std::move(resource), reason] {
2545 RTC_DCHECK_RUN_ON(&encoder_queue_);
2546 additional_resources_.push_back(resource);
2547 stream_resource_manager_.AddResource(resource, reason);
2548 });
2549 }
2550
InjectAdaptationConstraint(AdaptationConstraint * adaptation_constraint)2551 void VideoStreamEncoder::InjectAdaptationConstraint(
2552 AdaptationConstraint* adaptation_constraint) {
2553 rtc::Event event;
2554 encoder_queue_.PostTask([this, adaptation_constraint, &event] {
2555 RTC_DCHECK_RUN_ON(&encoder_queue_);
2556 if (!resource_adaptation_processor_) {
2557 // The VideoStreamEncoder was stopped and the processor destroyed before
2558 // this task had a chance to execute. No action needed.
2559 return;
2560 }
2561 adaptation_constraints_.push_back(adaptation_constraint);
2562 video_stream_adapter_->AddAdaptationConstraint(adaptation_constraint);
2563 event.Set();
2564 });
2565 event.Wait(rtc::Event::kForever);
2566 }
2567
AddRestrictionsListenerForTesting(VideoSourceRestrictionsListener * restrictions_listener)2568 void VideoStreamEncoder::AddRestrictionsListenerForTesting(
2569 VideoSourceRestrictionsListener* restrictions_listener) {
2570 rtc::Event event;
2571 encoder_queue_.PostTask([this, restrictions_listener, &event] {
2572 RTC_DCHECK_RUN_ON(&encoder_queue_);
2573 RTC_DCHECK(resource_adaptation_processor_);
2574 video_stream_adapter_->AddRestrictionsListener(restrictions_listener);
2575 event.Set();
2576 });
2577 event.Wait(rtc::Event::kForever);
2578 }
2579
RemoveRestrictionsListenerForTesting(VideoSourceRestrictionsListener * restrictions_listener)2580 void VideoStreamEncoder::RemoveRestrictionsListenerForTesting(
2581 VideoSourceRestrictionsListener* restrictions_listener) {
2582 rtc::Event event;
2583 encoder_queue_.PostTask([this, restrictions_listener, &event] {
2584 RTC_DCHECK_RUN_ON(&encoder_queue_);
2585 RTC_DCHECK(resource_adaptation_processor_);
2586 video_stream_adapter_->RemoveRestrictionsListener(restrictions_listener);
2587 event.Set();
2588 });
2589 event.Wait(rtc::Event::kForever);
2590 }
2591
2592 } // namespace webrtc
2593