| Index: webrtc/video/vie_encoder.cc
|
| diff --git a/webrtc/video/vie_encoder.cc b/webrtc/video/vie_encoder.cc
|
| index 1458af266f68efb6692756205f2296b6cd217e20..995af4dd099613864a814e625f6b0515ab62d27f 100644
|
| --- a/webrtc/video/vie_encoder.cc
|
| +++ b/webrtc/video/vie_encoder.cc
|
| @@ -163,9 +163,21 @@ class ViEEncoder::VideoSourceProxy {
|
| {
|
| rtc::CritScope lock(&crit_);
|
| old_source = source_;
|
| - source_ = source;
|
| + wants = sink_wants_;
|
| + // If changing degradation preference, clear any constraints from the
|
| + // current sink wants that will no longer apply.
|
| + if (degradation_preference_ != degradation_preference) {
|
| + switch (degradation_preference) {
|
| + case DegradationPreference::kBalanced:
|
| + wants.framerate_fps_.reset();
|
| + break;
|
| + case DegradationPreference::kMaintainResolution:
|
| + wants.pixel_count.reset();
|
| + break;
|
| + }
|
| + }
|
| degradation_preference_ = degradation_preference;
|
| - wants = current_wants();
|
| + source_ = source;
|
| }
|
|
|
| if (old_source != source && old_source != nullptr) {
|
| @@ -182,9 +194,8 @@ class ViEEncoder::VideoSourceProxy {
|
| void SetWantsRotationApplied(bool rotation_applied) {
|
| rtc::CritScope lock(&crit_);
|
| sink_wants_.rotation_applied = rotation_applied;
|
| - disabled_scaling_sink_wants_.rotation_applied = rotation_applied;
|
| if (source_) {
|
| - source_->AddOrUpdateSink(vie_encoder_, current_wants());
|
| + source_->AddOrUpdateSink(vie_encoder_, sink_wants_);
|
| }
|
| }
|
|
|
| @@ -203,12 +214,16 @@ class ViEEncoder::VideoSourceProxy {
|
| const int pixels_wanted = (pixel_count * 3) / 5;
|
| if (pixels_wanted < kMinPixelsPerFrame)
|
| return;
|
| - sink_wants_.max_pixel_count = rtc::Optional<int>(pixels_wanted);
|
| - sink_wants_.target_pixel_count = rtc::Optional<int>();
|
| + sink_wants_.pixel_count.emplace(rtc::VideoSinkWants::Range(
|
| + kMinPixelsPerFrame, pixels_wanted, pixel_count - 1));
|
| if (source_)
|
| source_->AddOrUpdateSink(vie_encoder_, sink_wants_);
|
| }
|
|
|
| + void RequestFramerateLowerThan(int framerate_fps) {
|
| + // TODO(sprang): Update SinkWants.
|
| + }
|
| +
|
| void RequestHigherResolutionThan(int pixel_count) {
|
| rtc::CritScope lock(&crit_);
|
| if (!IsResolutionScalingEnabledLocked()) {
|
| @@ -217,18 +232,21 @@ class ViEEncoder::VideoSourceProxy {
|
| // task queue.
|
| return;
|
| }
|
| - // On step down we request at most 3/5 the pixel count of the previous
|
| - // resolution, so in order to take "one step up" we request a resolution as
|
| - // close as possible to 5/3 of the current resolution. The actual pixel
|
| - // count selected depends on the capabilities of the source. In order to not
|
| - // take a too large step up, we cap the requested pixel count to be at most
|
| - // four time the current number of pixels.
|
| - sink_wants_.target_pixel_count = rtc::Optional<int>((pixel_count * 5) / 3);
|
| - sink_wants_.max_pixel_count = rtc::Optional<int>(pixel_count * 4);
|
| +
|
| + // The input video frame size will have a resolution with "one step up"
|
| + // pixels than |max_pixel_count_step_up| where "one step up" depends on
|
| + // how the source can scale the input frame size. We still cap the step up
|
| + // to be at most twice the number of pixels.
|
| + sink_wants_.pixel_count.emplace(rtc::VideoSinkWants::Range(
|
| + pixel_count + 1, (pixel_count * 5) / 3, pixel_count * 4));
|
| if (source_)
|
| source_->AddOrUpdateSink(vie_encoder_, sink_wants_);
|
| }
|
|
|
| + void RequestHigherFramerateThan(int framerate_fps) {
|
| + // TODO(sprang): Update SinkWants.
|
| + }
|
| +
|
| private:
|
| bool IsResolutionScalingEnabledLocked() const
|
| EXCLUSIVE_LOCKS_REQUIRED(&crit_) {
|
| @@ -236,17 +254,16 @@ class ViEEncoder::VideoSourceProxy {
|
| DegradationPreference::kMaintainResolution;
|
| }
|
|
|
| - const rtc::VideoSinkWants& current_wants() const
|
| + bool IsFramerateScalingEnabledLocked() const
|
| EXCLUSIVE_LOCKS_REQUIRED(&crit_) {
|
| - return IsResolutionScalingEnabledLocked() ? sink_wants_
|
| - : disabled_scaling_sink_wants_;
|
| + return degradation_preference_ ==
|
| + DegradationPreference::kMaintainResolution;
|
| }
|
|
|
| rtc::CriticalSection crit_;
|
| rtc::SequencedTaskChecker main_checker_;
|
| ViEEncoder* const vie_encoder_;
|
| rtc::VideoSinkWants sink_wants_ GUARDED_BY(&crit_);
|
| - rtc::VideoSinkWants disabled_scaling_sink_wants_ GUARDED_BY(&crit_);
|
| DegradationPreference degradation_preference_ GUARDED_BY(&crit_);
|
| rtc::VideoSourceInterface<VideoFrame>* source_ GUARDED_BY(&crit_);
|
|
|
| @@ -741,19 +758,37 @@ void ViEEncoder::OnBitrateUpdated(uint32_t bitrate_bps,
|
|
|
| void ViEEncoder::AdaptDown(AdaptReason reason) {
|
| RTC_DCHECK_RUN_ON(&encoder_queue_);
|
| - if (degradation_preference_ != DegradationPreference::kBalanced)
|
| - return;
|
| - RTC_DCHECK(static_cast<bool>(last_frame_info_));
|
| - int current_pixel_count = last_frame_info_->pixel_count();
|
| + AdaptationRequest adaptation_request = {
|
| + last_frame_info_->pixel_count(),
|
| + stats_proxy_->GetStats().input_frame_rate,
|
| + AdaptationRequest::Mode::kAdaptDown};
|
| +
|
| if (last_adaptation_request_ &&
|
| - last_adaptation_request_->mode_ == AdaptationRequest::Mode::kAdaptDown &&
|
| - current_pixel_count >= last_adaptation_request_->input_pixel_count_) {
|
| - // Don't request lower resolution if the current resolution is not lower
|
| - // than the last time we asked for the resolution to be lowered.
|
| - return;
|
| + last_adaptation_request_->mode_ == AdaptationRequest::Mode::kAdaptDown) {
|
| + switch (degradation_preference_) {
|
| + case DegradationPreference::kBalanced:
|
| + if (adaptation_request.input_pixel_count_ >=
|
| + last_adaptation_request_->input_pixel_count_) {
|
| + // Don't request lower resolution if the current resolution is not
|
| + // lower
|
| + // than the last time we asked for the resolution to be lowered.
|
| + return;
|
| + }
|
| + break;
|
| + case DegradationPreference::kMaintainResolution:
|
| + if (adaptation_request.framerate_fps_ <= 1) {
|
| + // Don't request lower framerate if we don't have a valid frame rate.
|
| + // Since framerate, unlike resolution, is a measure we have to
|
| + // estimate, and can fluctuate naturally over time, don't make the
|
| + // same kind of limitations as for resolution, but trust the overuse
|
| + // detector to not trigger too often.
|
| + return;
|
| + }
|
| + break;
|
| + }
|
| }
|
| - last_adaptation_request_.emplace(AdaptationRequest{
|
| - current_pixel_count, AdaptationRequest::Mode::kAdaptDown});
|
| +
|
| + last_adaptation_request_.emplace(adaptation_request);
|
|
|
| switch (reason) {
|
| case kQuality:
|
| @@ -768,8 +803,20 @@ void ViEEncoder::AdaptDown(AdaptReason reason) {
|
| break;
|
| }
|
| ++scale_counter_[reason];
|
| - source_proxy_->RequestResolutionLowerThan(current_pixel_count);
|
| - LOG(LS_INFO) << "Scaling down resolution.";
|
| +
|
| + switch (degradation_preference_) {
|
| + case DegradationPreference::kBalanced:
|
| + source_proxy_->RequestResolutionLowerThan(
|
| + adaptation_request.input_pixel_count_);
|
| + LOG(LS_INFO) << "Scaling down resolution.";
|
| + break;
|
| + case DegradationPreference::kMaintainResolution:
|
| + source_proxy_->RequestFramerateLowerThan(
|
| + adaptation_request.framerate_fps_);
|
| + LOG(LS_INFO) << "Scaling down framerate.";
|
| + break;
|
| + }
|
| +
|
| for (size_t i = 0; i < kScaleReasonSize; ++i) {
|
| LOG(LS_INFO) << "Scaled " << scale_counter_[i]
|
| << " times for reason: " << (i ? "cpu" : "quality");
|
| @@ -782,19 +829,31 @@ void ViEEncoder::AdaptUp(AdaptReason reason) {
|
| degradation_preference_ != DegradationPreference::kBalanced) {
|
| return;
|
| }
|
| - // Only scale if resolution is higher than last time we requested higher
|
| - // resolution.
|
| - RTC_DCHECK(static_cast<bool>(last_frame_info_));
|
| - int current_pixel_count = last_frame_info_->pixel_count();
|
| +
|
| + AdaptationRequest adaptation_request = {
|
| + last_frame_info_->pixel_count(),
|
| + stats_proxy_->GetStats().input_frame_rate,
|
| + AdaptationRequest::Mode::kAdaptUp};
|
| +
|
| if (last_adaptation_request_ &&
|
| - last_adaptation_request_->mode_ == AdaptationRequest::Mode::kAdaptUp &&
|
| - current_pixel_count <= last_adaptation_request_->input_pixel_count_) {
|
| - // Don't request higher resolution if the current resolution is not higher
|
| - // than the last time we asked for the resolution to be higher.
|
| - return;
|
| + last_adaptation_request_->mode_ == AdaptationRequest::Mode::kAdaptUp) {
|
| + switch (degradation_preference_) {
|
| + case DegradationPreference::kBalanced:
|
| + if (adaptation_request.input_pixel_count_ <=
|
| + last_adaptation_request_->input_pixel_count_) {
|
| + // Don't request higher resolution if the current resolution is not
|
| + // higher than the last time we asked for the resolution to be higher.
|
| + return;
|
| + }
|
| + break;
|
| + case DegradationPreference::kMaintainResolution:
|
| + // TODO(sprang): Don't request higher framerate if we are already at
|
| + // max requested fps?
|
| + break;
|
| + }
|
| }
|
| - last_adaptation_request_.emplace(AdaptationRequest{
|
| - current_pixel_count, AdaptationRequest::Mode::kAdaptUp});
|
| +
|
| + last_adaptation_request_.emplace(adaptation_request);
|
|
|
| switch (reason) {
|
| case kQuality:
|
| @@ -808,8 +867,20 @@ void ViEEncoder::AdaptUp(AdaptReason reason) {
|
| break;
|
| }
|
| --scale_counter_[reason];
|
| - source_proxy_->RequestHigherResolutionThan(current_pixel_count);
|
| - LOG(LS_INFO) << "Scaling up resolution.";
|
| +
|
| + switch (degradation_preference_) {
|
| + case DegradationPreference::kBalanced:
|
| + source_proxy_->RequestHigherResolutionThan(
|
| + adaptation_request.input_pixel_count_);
|
| + LOG(LS_INFO) << "Scaling up resolution.";
|
| + break;
|
| + case DegradationPreference::kMaintainResolution:
|
| + source_proxy_->RequestHigherFramerateThan(
|
| + adaptation_request.framerate_fps_);
|
| + LOG(LS_INFO) << "Scaling up framerate.";
|
| + break;
|
| + }
|
| +
|
| for (size_t i = 0; i < kScaleReasonSize; ++i) {
|
| LOG(LS_INFO) << "Scaled " << scale_counter_[i]
|
| << " times for reason: " << (i ? "cpu" : "quality");
|
|
|