| Index: webrtc/video/vie_encoder.cc
|
| diff --git a/webrtc/video/vie_encoder.cc b/webrtc/video/vie_encoder.cc
|
| index 203d1c405a8813d05b627cd464803bb9df39f645..63b1c80fefbe9b0f0f8afaf95a83dd0f140a3540 100644
|
| --- a/webrtc/video/vie_encoder.cc
|
| +++ b/webrtc/video/vie_encoder.cc
|
| @@ -73,6 +73,29 @@ uint32_t MaximumFrameSizeForBitrate(uint32_t kbps) {
|
| return std::numeric_limits<uint32_t>::max();
|
| }
|
|
|
| +// Initial limits for kBalanced degradation preference.
|
| +int MinFps(int pixels) {
|
| + if (pixels <= 320 * 240) {
|
| + return 7;
|
| + } else if (pixels <= 480 * 270) {
|
| + return 10;
|
| + } else if (pixels <= 640 * 480) {
|
| + return 15;
|
| + } else {
|
| + return std::numeric_limits<int>::max();
|
| + }
|
| +}
|
| +
|
| +int MaxFps(int pixels) {
|
| + if (pixels <= 320 * 240) {
|
| + return 10;
|
| + } else if (pixels <= 480 * 270) {
|
| + return 15;
|
| + } else {
|
| + return std::numeric_limits<int>::max();
|
| + }
|
| +}
|
| +
|
| bool IsResolutionScalingEnabled(
|
| VideoSendStream::DegradationPreference degradation_preference) {
|
| return degradation_preference ==
|
| @@ -211,7 +234,7 @@ class ViEEncoder::VideoSourceProxy {
|
| // the used degradation_preference.
|
| switch (degradation_preference_) {
|
| case VideoSendStream::DegradationPreference::kBalanced:
|
| - FALLTHROUGH();
|
| + break;
|
| case VideoSendStream::DegradationPreference::kMaintainFramerate:
|
| wants.max_framerate_fps = std::numeric_limits<int>::max();
|
| break;
|
| @@ -227,6 +250,15 @@ class ViEEncoder::VideoSourceProxy {
|
| return wants;
|
| }
|
|
|
| + void ResetPixelFpsCount() {
|
| + rtc::CritScope lock(&crit_);
|
| + sink_wants_.max_pixel_count = std::numeric_limits<int>::max();
|
| + sink_wants_.target_pixel_count.reset();
|
| + sink_wants_.max_framerate_fps = std::numeric_limits<int>::max();
|
| + if (source_)
|
| + source_->AddOrUpdateSink(vie_encoder_, sink_wants_);
|
| + }
|
| +
|
| bool RequestResolutionLowerThan(int pixel_count) {
|
| // Called on the encoder task queue.
|
| rtc::CritScope lock(&crit_);
|
| @@ -447,6 +479,15 @@ void ViEEncoder::SetSource(
|
| // Reset adaptation state, so that we're not tricked into thinking there's
|
| // an already pending request of the same type.
|
| last_adaptation_request_.reset();
|
| + if (degradation_preference ==
|
| + VideoSendStream::DegradationPreference::kBalanced ||
|
| + degradation_preference_ ==
|
| + VideoSendStream::DegradationPreference::kBalanced) {
|
| + // TODO(asapersson): Consider removing |adapt_counters_| map and use one
|
| + // AdaptCounter for all modes.
|
| + source_proxy_->ResetPixelFpsCount();
|
| + adapt_counters_.clear();
|
| + }
|
| }
|
| degradation_preference_ = degradation_preference;
|
| bool allow_scaling = IsResolutionScalingEnabled(degradation_preference_);
|
| @@ -803,12 +844,10 @@ void ViEEncoder::AdaptDown(AdaptReason reason) {
|
| last_adaptation_request_ &&
|
| last_adaptation_request_->mode_ == AdaptationRequest::Mode::kAdaptDown;
|
|
|
| - int max_downgrades = 0;
|
| switch (degradation_preference_) {
|
| case VideoSendStream::DegradationPreference::kBalanced:
|
| - FALLTHROUGH();
|
| + break;
|
| case VideoSendStream::DegradationPreference::kMaintainFramerate:
|
| - max_downgrades = kMaxCpuResolutionDowngrades;
|
| if (downgrade_requested &&
|
| adaptation_request.input_pixel_count_ >=
|
| last_adaptation_request_->input_pixel_count_) {
|
| @@ -818,7 +857,6 @@ void ViEEncoder::AdaptDown(AdaptReason reason) {
|
| }
|
| break;
|
| case VideoSendStream::DegradationPreference::kMaintainResolution:
|
| - max_downgrades = kMaxCpuFramerateDowngrades;
|
| if (adaptation_request.framerate_fps_ <= 0 ||
|
| (downgrade_requested &&
|
| adaptation_request.framerate_fps_ < kMinFramerateFps)) {
|
| @@ -836,20 +874,32 @@ void ViEEncoder::AdaptDown(AdaptReason reason) {
|
| }
|
|
|
| if (reason == kCpu) {
|
| - if (GetConstAdaptCounter().TotalCount(kCpu) >= max_downgrades)
|
| + if (GetConstAdaptCounter().ResolutionCount(kCpu) >=
|
| + kMaxCpuResolutionDowngrades ||
|
| + GetConstAdaptCounter().FramerateCount(kCpu) >=
|
| + kMaxCpuFramerateDowngrades) {
|
| return;
|
| + }
|
| }
|
|
|
| switch (degradation_preference_) {
|
| - case VideoSendStream::DegradationPreference::kBalanced:
|
| + case VideoSendStream::DegradationPreference::kBalanced: {
|
| + // Try scale down framerate, if lower.
|
| + int fps = MinFps(last_frame_info_->pixel_count());
|
| + if (source_proxy_->RestrictFramerate(fps)) {
|
| + GetAdaptCounter().IncrementFramerate(reason);
|
| + break;
|
| + }
|
| + // Scale down resolution.
|
| FALLTHROUGH();
|
| + }
|
| case VideoSendStream::DegradationPreference::kMaintainFramerate:
|
| // Scale down resolution.
|
| if (!source_proxy_->RequestResolutionLowerThan(
|
| adaptation_request.input_pixel_count_)) {
|
| return;
|
| }
|
| - GetAdaptCounter().IncrementResolution(reason, 1);
|
| + GetAdaptCounter().IncrementResolution(reason);
|
| break;
|
| case VideoSendStream::DegradationPreference::kMaintainResolution:
|
| // Scale down framerate.
|
| @@ -857,7 +907,7 @@ void ViEEncoder::AdaptDown(AdaptReason reason) {
|
| adaptation_request.framerate_fps_)) {
|
| return;
|
| }
|
| - GetAdaptCounter().IncrementFramerate(reason, 1);
|
| + GetAdaptCounter().IncrementFramerate(reason);
|
| break;
|
| case VideoSendStream::DegradationPreference::kDegradationDisabled:
|
| RTC_NOTREACHED();
|
| @@ -888,29 +938,34 @@ void ViEEncoder::AdaptUp(AdaptReason reason) {
|
| last_adaptation_request_ &&
|
| last_adaptation_request_->mode_ == AdaptationRequest::Mode::kAdaptUp;
|
|
|
| - switch (degradation_preference_) {
|
| - case VideoSendStream::DegradationPreference::kBalanced:
|
| - FALLTHROUGH();
|
| - case VideoSendStream::DegradationPreference::kMaintainFramerate:
|
| - if (adapt_up_requested &&
|
| - 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 VideoSendStream::DegradationPreference::kMaintainResolution:
|
| - // TODO(sprang): Don't request higher framerate if we are already at
|
| - // max requested fps?
|
| - break;
|
| - case VideoSendStream::DegradationPreference::kDegradationDisabled:
|
| + if (degradation_preference_ ==
|
| + VideoSendStream::DegradationPreference::kMaintainFramerate) {
|
| + if (adapt_up_requested &&
|
| + 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;
|
| + }
|
| }
|
|
|
| switch (degradation_preference_) {
|
| - case VideoSendStream::DegradationPreference::kBalanced:
|
| + case VideoSendStream::DegradationPreference::kBalanced: {
|
| + // Try scale up framerate, if higher.
|
| + int fps = MaxFps(last_frame_info_->pixel_count());
|
| + if (source_proxy_->IncreaseFramerate(fps)) {
|
| + GetAdaptCounter().DecrementFramerate(reason, fps);
|
| + // Reset framerate in case of fewer fps steps down than up.
|
| + if (adapt_counter.FramerateCount() == 0 &&
|
| + fps != std::numeric_limits<int>::max()) {
|
| + LOG(LS_INFO) << "Removing framerate down-scaling setting.";
|
| + source_proxy_->IncreaseFramerate(std::numeric_limits<int>::max());
|
| + }
|
| + break;
|
| + }
|
| + // Scale up resolution.
|
| FALLTHROUGH();
|
| + }
|
| case VideoSendStream::DegradationPreference::kMaintainFramerate: {
|
| // Scale up resolution.
|
| int pixel_count = adaptation_request.input_pixel_count_;
|
| @@ -920,7 +975,7 @@ void ViEEncoder::AdaptUp(AdaptReason reason) {
|
| }
|
| if (!source_proxy_->RequestHigherResolutionThan(pixel_count))
|
| return;
|
| - GetAdaptCounter().IncrementResolution(reason, -1);
|
| + GetAdaptCounter().DecrementResolution(reason);
|
| break;
|
| }
|
| case VideoSendStream::DegradationPreference::kMaintainResolution: {
|
| @@ -932,11 +987,11 @@ void ViEEncoder::AdaptUp(AdaptReason reason) {
|
| }
|
| if (!source_proxy_->RequestHigherFramerateThan(fps))
|
| return;
|
| - GetAdaptCounter().IncrementFramerate(reason, -1);
|
| + GetAdaptCounter().DecrementFramerate(reason);
|
| break;
|
| }
|
| case VideoSendStream::DegradationPreference::kDegradationDisabled:
|
| - RTC_NOTREACHED();
|
| + return;
|
| }
|
|
|
| last_adaptation_request_.emplace(adaptation_request);
|
| @@ -994,6 +1049,7 @@ const ViEEncoder::AdaptCounter& ViEEncoder::GetConstAdaptCounter() {
|
| ViEEncoder::AdaptCounter::AdaptCounter() {
|
| fps_counters_.resize(kScaleReasonSize);
|
| resolution_counters_.resize(kScaleReasonSize);
|
| + static_assert(kScaleReasonSize == 2, "Update MoveCount.");
|
| }
|
|
|
| ViEEncoder::AdaptCounter::~AdaptCounter() {}
|
| @@ -1012,12 +1068,48 @@ ViEEncoder::AdaptCounts ViEEncoder::AdaptCounter::Counts(int reason) const {
|
| return counts;
|
| }
|
|
|
| -void ViEEncoder::AdaptCounter::IncrementFramerate(int reason, int delta) {
|
| - fps_counters_[reason] += delta;
|
| +void ViEEncoder::AdaptCounter::IncrementFramerate(int reason) {
|
| + ++(fps_counters_[reason]);
|
| +}
|
| +
|
| +void ViEEncoder::AdaptCounter::IncrementResolution(int reason) {
|
| + ++(resolution_counters_[reason]);
|
| }
|
|
|
| -void ViEEncoder::AdaptCounter::IncrementResolution(int reason, int delta) {
|
| - resolution_counters_[reason] += delta;
|
| +void ViEEncoder::AdaptCounter::DecrementFramerate(int reason) {
|
| + if (fps_counters_[reason] == 0) {
|
| + // Balanced mode: Adapt up is in a different order, switch reason.
|
| + // E.g. framerate adapt down: quality (2), framerate adapt up: cpu (3).
|
| + // 1. Down resolution (cpu): res={quality:0,cpu:1}, fps={quality:0,cpu:0}
|
| + // 2. Down fps (quality): res={quality:0,cpu:1}, fps={quality:1,cpu:0}
|
| + // 3. Up fps (cpu): res={quality:1,cpu:0}, fps={quality:0,cpu:0}
|
| + // 4. Up resolution (quality): res={quality:0,cpu:0}, fps={quality:0,cpu:0}
|
| + RTC_DCHECK_GT(TotalCount(reason), 0) << "No downgrade for reason.";
|
| + RTC_DCHECK_GT(FramerateCount(), 0) << "Framerate not downgraded.";
|
| + MoveCount(&resolution_counters_, reason);
|
| + MoveCount(&fps_counters_, (reason + 1) % kScaleReasonSize);
|
| + }
|
| + --(fps_counters_[reason]);
|
| + RTC_DCHECK_GE(fps_counters_[reason], 0);
|
| +}
|
| +
|
| +void ViEEncoder::AdaptCounter::DecrementResolution(int reason) {
|
| + if (resolution_counters_[reason] == 0) {
|
| + // Balanced mode: Adapt up is in a different order, switch reason.
|
| + RTC_DCHECK_GT(TotalCount(reason), 0) << "No downgrade for reason.";
|
| + RTC_DCHECK_GT(ResolutionCount(), 0) << "Resolution not downgraded.";
|
| + MoveCount(&fps_counters_, reason);
|
| + MoveCount(&resolution_counters_, (reason + 1) % kScaleReasonSize);
|
| + }
|
| + --(resolution_counters_[reason]);
|
| + RTC_DCHECK_GE(resolution_counters_[reason], 0);
|
| +}
|
| +
|
| +void ViEEncoder::AdaptCounter::DecrementFramerate(int reason, int cur_fps) {
|
| + DecrementFramerate(reason);
|
| + // Reset if at max fps (i.e. in case of fewer steps up than down).
|
| + if (cur_fps == std::numeric_limits<int>::max())
|
| + std::fill(fps_counters_.begin(), fps_counters_.end(), 0);
|
| }
|
|
|
| int ViEEncoder::AdaptCounter::FramerateCount() const {
|
| @@ -1028,10 +1120,6 @@ int ViEEncoder::AdaptCounter::ResolutionCount() const {
|
| return Count(resolution_counters_);
|
| }
|
|
|
| -int ViEEncoder::AdaptCounter::TotalCount() const {
|
| - return FramerateCount() + ResolutionCount();
|
| -}
|
| -
|
| int ViEEncoder::AdaptCounter::FramerateCount(int reason) const {
|
| return fps_counters_[reason];
|
| }
|
| @@ -1048,6 +1136,13 @@ int ViEEncoder::AdaptCounter::Count(const std::vector<int>& counters) const {
|
| return std::accumulate(counters.begin(), counters.end(), 0);
|
| }
|
|
|
| +void ViEEncoder::AdaptCounter::MoveCount(std::vector<int>* counters,
|
| + int from_reason) {
|
| + int to_reason = (from_reason + 1) % kScaleReasonSize;
|
| + ++((*counters)[to_reason]);
|
| + --((*counters)[from_reason]);
|
| +}
|
| +
|
| std::string ViEEncoder::AdaptCounter::ToString(
|
| const std::vector<int>& counters) const {
|
| std::stringstream ss;
|
|
|