Commit dd6a406a authored by Yuri Wiitala's avatar Yuri Wiitala Committed by Commit Bot

Require consumer feedback signal before activating auto-throttling.

VideoCaptureOracle, which is used by viz::FrameSinkVideoCapturer
includes logic to suggest capture size changes in response to
bottlenecks in an end-to-end screen mirroring pipeline. This change
prevents the oracle from reducing the capture size until after it
confirms a downstream consumer of the video capture is providing the
necessary feedback signals.

Bug: 1092854
Change-Id: Iadf059548cc1ae705cbcf1e40283fd115563a8bd
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2298579
Commit-Queue: Takumi Fujimoto <takumif@chromium.org>
Reviewed-by: default avatarTakumi Fujimoto <takumif@chromium.org>
Auto-Submit: Yuri Wiitala <miu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#790003}
parent 70c537ae
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
#include "media/capture/content/video_capture_oracle.h" #include "media/capture/content/video_capture_oracle.h"
#include <algorithm> #include <algorithm>
#include <limits>
#include <utility>
#include "base/callback.h" #include "base/callback.h"
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
...@@ -79,7 +81,8 @@ constexpr base::TimeDelta VideoCaptureOracle::kDefaultMinCapturePeriod; ...@@ -79,7 +81,8 @@ constexpr base::TimeDelta VideoCaptureOracle::kDefaultMinCapturePeriod;
constexpr base::TimeDelta VideoCaptureOracle::kDefaultMinSizeChangePeriod; constexpr base::TimeDelta VideoCaptureOracle::kDefaultMinSizeChangePeriod;
VideoCaptureOracle::VideoCaptureOracle(bool enable_auto_throttling) VideoCaptureOracle::VideoCaptureOracle(bool enable_auto_throttling)
: auto_throttling_enabled_(enable_auto_throttling), : capture_size_throttling_mode_(
enable_auto_throttling ? kThrottlingEnabled : kThrottlingDisabled),
min_size_change_period_(kDefaultMinSizeChangePeriod), min_size_change_period_(kDefaultMinSizeChangePeriod),
next_frame_number_(0), next_frame_number_(0),
last_successfully_delivered_frame_number_(-1), last_successfully_delivered_frame_number_(-1),
...@@ -90,8 +93,8 @@ VideoCaptureOracle::VideoCaptureOracle(bool enable_auto_throttling) ...@@ -90,8 +93,8 @@ VideoCaptureOracle::VideoCaptureOracle(bool enable_auto_throttling)
kBufferUtilizationEvaluationMicros)), kBufferUtilizationEvaluationMicros)),
estimated_capable_area_(base::TimeDelta::FromMicroseconds( estimated_capable_area_(base::TimeDelta::FromMicroseconds(
kConsumerCapabilityEvaluationMicros)) { kConsumerCapabilityEvaluationMicros)) {
VLOG(1) << "Auto-throttling is " VLOG(1) << "Capture size auto-throttling is now "
<< (auto_throttling_enabled_ ? "enabled." : "disabled."); << (enable_auto_throttling ? "enabled." : "disabled.");
} }
VideoCaptureOracle::~VideoCaptureOracle() = default; VideoCaptureOracle::~VideoCaptureOracle() = default;
...@@ -111,9 +114,14 @@ void VideoCaptureOracle::SetCaptureSizeConstraints( ...@@ -111,9 +114,14 @@ void VideoCaptureOracle::SetCaptureSizeConstraints(
} }
void VideoCaptureOracle::SetAutoThrottlingEnabled(bool enabled) { void VideoCaptureOracle::SetAutoThrottlingEnabled(bool enabled) {
if (auto_throttling_enabled_ == enabled) const bool was_enabled =
(capture_size_throttling_mode_ != kThrottlingDisabled);
if (was_enabled == enabled)
return; return;
auto_throttling_enabled_ = enabled; capture_size_throttling_mode_ =
enabled ? kThrottlingEnabled : kThrottlingDisabled;
VLOG(1) << "Capture size auto-throttling is now "
<< (enabled ? "enabled." : "disabled.");
// When not auto-throttling, have the CaptureResolutionChooser target the max // When not auto-throttling, have the CaptureResolutionChooser target the max
// resolution within constraints. // resolution within constraints.
...@@ -225,7 +233,7 @@ void VideoCaptureOracle::RecordCapture(double pool_utilization) { ...@@ -225,7 +233,7 @@ void VideoCaptureOracle::RecordCapture(double pool_utilization) {
const base::TimeTicks timestamp = GetFrameTimestamp(next_frame_number_); const base::TimeTicks timestamp = GetFrameTimestamp(next_frame_number_);
content_sampler_.RecordSample(timestamp); content_sampler_.RecordSample(timestamp);
if (auto_throttling_enabled_) { if (capture_size_throttling_mode_ == kThrottlingActive) {
buffer_pool_utilization_.Update(pool_utilization, timestamp); buffer_pool_utilization_.Update(pool_utilization, timestamp);
AnalyzeAndAdjust(timestamp); AnalyzeAndAdjust(timestamp);
} }
...@@ -238,7 +246,7 @@ void VideoCaptureOracle::RecordWillNotCapture(double pool_utilization) { ...@@ -238,7 +246,7 @@ void VideoCaptureOracle::RecordWillNotCapture(double pool_utilization) {
VLOG(1) << "Client rejects proposal to capture frame (at #" VLOG(1) << "Client rejects proposal to capture frame (at #"
<< next_frame_number_ << ")."; << next_frame_number_ << ").";
if (auto_throttling_enabled_) { if (capture_size_throttling_mode_ == kThrottlingActive) {
DCHECK(std::isfinite(pool_utilization) && pool_utilization >= 0.0); DCHECK(std::isfinite(pool_utilization) && pool_utilization >= 0.0);
const base::TimeTicks timestamp = GetFrameTimestamp(next_frame_number_); const base::TimeTicks timestamp = GetFrameTimestamp(next_frame_number_);
buffer_pool_utilization_.Update(pool_utilization, timestamp); buffer_pool_utilization_.Update(pool_utilization, timestamp);
...@@ -326,7 +334,7 @@ void VideoCaptureOracle::CancelAllCaptures() { ...@@ -326,7 +334,7 @@ void VideoCaptureOracle::CancelAllCaptures() {
void VideoCaptureOracle::RecordConsumerFeedback(int frame_number, void VideoCaptureOracle::RecordConsumerFeedback(int frame_number,
double resource_utilization) { double resource_utilization) {
if (!auto_throttling_enabled_) if (capture_size_throttling_mode_ == kThrottlingDisabled)
return; return;
if (!std::isfinite(resource_utilization)) { if (!std::isfinite(resource_utilization)) {
...@@ -337,6 +345,12 @@ void VideoCaptureOracle::RecordConsumerFeedback(int frame_number, ...@@ -337,6 +345,12 @@ void VideoCaptureOracle::RecordConsumerFeedback(int frame_number,
if (resource_utilization <= 0.0) if (resource_utilization <= 0.0)
return; // Non-positive values are normal, meaning N/A. return; // Non-positive values are normal, meaning N/A.
if (capture_size_throttling_mode_ != kThrottlingActive) {
VLOG(1) << "Received consumer feedback at frame #" << frame_number
<< "; activating capture size auto-throttling.";
capture_size_throttling_mode_ = kThrottlingActive;
}
if (!IsFrameInRecentHistory(frame_number)) { if (!IsFrameInRecentHistory(frame_number)) {
VLOG(1) << "Very old frame feedback being ignored: frame #" << frame_number; VLOG(1) << "Very old frame feedback being ignored: frame #" << frame_number;
return; return;
...@@ -409,7 +423,7 @@ void VideoCaptureOracle::CommitCaptureSizeAndReset( ...@@ -409,7 +423,7 @@ void VideoCaptureOracle::CommitCaptureSizeAndReset(
} }
void VideoCaptureOracle::AnalyzeAndAdjust(const base::TimeTicks analyze_time) { void VideoCaptureOracle::AnalyzeAndAdjust(const base::TimeTicks analyze_time) {
DCHECK(auto_throttling_enabled_); DCHECK(capture_size_throttling_mode_ == kThrottlingActive);
const int decreased_area = AnalyzeForDecreasedArea(analyze_time); const int decreased_area = AnalyzeForDecreasedArea(analyze_time);
if (decreased_area > 0) { if (decreased_area > 0) {
......
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
#ifndef MEDIA_CAPTURE_CONTENT_VIDEO_CAPTURE_ORACLE_H_ #ifndef MEDIA_CAPTURE_CONTENT_VIDEO_CAPTURE_ORACLE_H_
#define MEDIA_CAPTURE_CONTENT_VIDEO_CAPTURE_ORACLE_H_ #define MEDIA_CAPTURE_CONTENT_VIDEO_CAPTURE_ORACLE_H_
#include <string>
#include "base/callback.h" #include "base/callback.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "media/base/feedback_signal_accumulator.h" #include "media/base/feedback_signal_accumulator.h"
...@@ -30,10 +32,9 @@ class CAPTURE_EXPORT VideoCaptureOracle { ...@@ -30,10 +32,9 @@ class CAPTURE_EXPORT VideoCaptureOracle {
// Constructs a VideoCaptureOracle with a default min capture period and // Constructs a VideoCaptureOracle with a default min capture period and
// capture size constraints. Clients should call SetMinCapturePeriod() and // capture size constraints. Clients should call SetMinCapturePeriod() and
// SetCaptureSizeConstraints() to provide more-accurate hard limits. If // SetCaptureSizeConstraints() to provide more-accurate hard limits.
// |enable_auto_throttling| is true, enable realtime analysis of system //
// performance and auto-adjust the capture resolution and sampling decisions // See SetAutoThrottlingEnabled() for |enable_auto_throttling| semantics.
// to provide the best user experience.
explicit VideoCaptureOracle(bool enable_auto_throttling); explicit VideoCaptureOracle(bool enable_auto_throttling);
virtual ~VideoCaptureOracle(); virtual ~VideoCaptureOracle();
...@@ -51,8 +52,11 @@ class CAPTURE_EXPORT VideoCaptureOracle { ...@@ -51,8 +52,11 @@ class CAPTURE_EXPORT VideoCaptureOracle {
const gfx::Size& max_size, const gfx::Size& max_size,
bool use_fixed_aspect_ratio); bool use_fixed_aspect_ratio);
// Specifies whether the oracle should automatically adjust the capture size // Specifies whether the oracle should propose varying capture sizes, in
// in response to end-to-end utilization. // response to consumer feedback. If not |enabled|, capture_size() will always
// return the source_size().
//
// See: SetMinSizeChangePeriod().
void SetAutoThrottlingEnabled(bool enabled); void SetAutoThrottlingEnabled(bool enabled);
// Get/Update the source content size. Changes may not have an immediate // Get/Update the source content size. Changes may not have an immediate
...@@ -161,7 +165,7 @@ class CAPTURE_EXPORT VideoCaptureOracle { ...@@ -161,7 +165,7 @@ class CAPTURE_EXPORT VideoCaptureOracle {
void CommitCaptureSizeAndReset(base::TimeTicks last_frame_time); void CommitCaptureSizeAndReset(base::TimeTicks last_frame_time);
// Called after a capture or no-capture decision was recorded. This analyzes // Called after a capture or no-capture decision was recorded. This analyzes
// current state and may result in a future change to the capture frame size. // current state and may result in a future change to the capture size.
void AnalyzeAndAdjust(base::TimeTicks analyze_time); void AnalyzeAndAdjust(base::TimeTicks analyze_time);
// Analyzes current feedback signal accumulators for an indication that the // Analyzes current feedback signal accumulators for an indication that the
...@@ -188,9 +192,15 @@ class CAPTURE_EXPORT VideoCaptureOracle { ...@@ -188,9 +192,15 @@ class CAPTURE_EXPORT VideoCaptureOracle {
const FeedbackSignalAccumulator<base::TimeTicks>& accumulator, const FeedbackSignalAccumulator<base::TimeTicks>& accumulator,
base::TimeTicks now); base::TimeTicks now);
// Set to false to prevent the oracle from automatically adjusting the capture // Set to disabled/enabled via SetAutoThrottlingEnabled(). Data collection and
// size in response to end-to-end utilization. // analysis for capture size changes only occurs while in "active" mode, which
bool auto_throttling_enabled_; // is only engaged when in "enabled" mode and consumer feedback is received
// for the first time.
enum {
kThrottlingDisabled,
kThrottlingEnabled,
kThrottlingActive
} capture_size_throttling_mode_;
// The minimum amount of time that must pass between changes to the capture // The minimum amount of time that must pass between changes to the capture
// size. // size.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment