Add configuration for ability to use the encode usage measure for triggering overuse/underuse.
BUG=1577 R=mflodman@webrtc.org Review URL: https://webrtc-codereview.appspot.com/10509004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@5767 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
b70c8e9dfd
commit
ce12f1fd32
@ -66,6 +66,9 @@ struct CpuOveruseOptions {
|
||||
: enable_capture_jitter_method(true),
|
||||
low_capture_jitter_threshold_ms(kNormalUseStdDevMs),
|
||||
high_capture_jitter_threshold_ms(kOveruseStdDevMs),
|
||||
enable_encode_usage_method(false),
|
||||
low_encode_usage_threshold_percent(60),
|
||||
high_encode_usage_threshold_percent(90),
|
||||
frame_timeout_interval_ms(1500),
|
||||
min_frame_samples(120),
|
||||
min_process_count(3),
|
||||
@ -75,6 +78,10 @@ struct CpuOveruseOptions {
|
||||
bool enable_capture_jitter_method;
|
||||
float low_capture_jitter_threshold_ms; // Threshold for triggering underuse.
|
||||
float high_capture_jitter_threshold_ms; // Threshold for triggering overuse.
|
||||
// Method based on encode time of frames.
|
||||
bool enable_encode_usage_method;
|
||||
int low_encode_usage_threshold_percent; // Threshold for triggering underuse.
|
||||
int high_encode_usage_threshold_percent; // Threshold for triggering overuse.
|
||||
// General settings.
|
||||
int frame_timeout_interval_ms; // The maximum allowed interval between two
|
||||
// frames before resetting estimations.
|
||||
@ -90,6 +97,11 @@ struct CpuOveruseOptions {
|
||||
low_capture_jitter_threshold_ms == o.low_capture_jitter_threshold_ms &&
|
||||
high_capture_jitter_threshold_ms ==
|
||||
o.high_capture_jitter_threshold_ms &&
|
||||
enable_encode_usage_method == o.enable_encode_usage_method &&
|
||||
low_encode_usage_threshold_percent ==
|
||||
o.low_encode_usage_threshold_percent &&
|
||||
high_encode_usage_threshold_percent ==
|
||||
o.high_encode_usage_threshold_percent &&
|
||||
frame_timeout_interval_ms == o.frame_timeout_interval_ms &&
|
||||
min_frame_samples == o.min_frame_samples &&
|
||||
min_process_count == o.min_process_count &&
|
||||
|
@ -140,13 +140,27 @@ class OveruseFrameDetector::EncodeUsage {
|
||||
EncodeUsage()
|
||||
: kWeightFactorFrameDiff(0.998f),
|
||||
kWeightFactorEncodeTime(0.995f),
|
||||
kInitialSampleDiffMs(50.0f),
|
||||
kMaxSampleDiffMs(66.0f),
|
||||
count_(0),
|
||||
filtered_encode_time_ms_(new VCMExpFilter(kWeightFactorEncodeTime)),
|
||||
filtered_frame_diff_ms_(new VCMExpFilter(kWeightFactorFrameDiff)) {
|
||||
filtered_encode_time_ms_->Apply(1.0f, kInitialAvgEncodeTimeMs);
|
||||
filtered_frame_diff_ms_->Apply(1.0f, kSampleDiffMs);
|
||||
Reset();
|
||||
}
|
||||
~EncodeUsage() {}
|
||||
|
||||
void SetOptions(const CpuOveruseOptions& options) {
|
||||
options_ = options;
|
||||
}
|
||||
|
||||
void Reset() {
|
||||
count_ = 0;
|
||||
filtered_frame_diff_ms_->Reset(kWeightFactorFrameDiff);
|
||||
filtered_frame_diff_ms_->Apply(1.0f, kInitialSampleDiffMs);
|
||||
filtered_encode_time_ms_->Reset(kWeightFactorEncodeTime);
|
||||
filtered_encode_time_ms_->Apply(1.0f, InitialEncodeTimeMs());
|
||||
}
|
||||
|
||||
void AddSample(float sample_ms) {
|
||||
float exp = sample_ms / kSampleDiffMs;
|
||||
exp = std::min(exp, kMaxExp);
|
||||
@ -154,21 +168,40 @@ class OveruseFrameDetector::EncodeUsage {
|
||||
}
|
||||
|
||||
void AddEncodeSample(float encode_time_ms, int64_t diff_last_sample_ms) {
|
||||
++count_;
|
||||
float exp = diff_last_sample_ms / kSampleDiffMs;
|
||||
exp = std::min(exp, kMaxExp);
|
||||
filtered_encode_time_ms_->Apply(exp, encode_time_ms);
|
||||
}
|
||||
|
||||
int UsageInPercent() const {
|
||||
if (count_ < static_cast<uint32_t>(options_.min_frame_samples)) {
|
||||
return static_cast<int>(InitialUsageInPercent() + 0.5f);
|
||||
}
|
||||
float frame_diff_ms = std::max(filtered_frame_diff_ms_->Value(), 1.0f);
|
||||
frame_diff_ms = std::min(frame_diff_ms, kMaxSampleDiffMs);
|
||||
float encode_usage_percent =
|
||||
100.0f * filtered_encode_time_ms_->Value() / frame_diff_ms;
|
||||
return static_cast<int>(encode_usage_percent + 0.5);
|
||||
}
|
||||
|
||||
float InitialUsageInPercent() const {
|
||||
// Start in between the underuse and overuse threshold.
|
||||
return (options_.low_encode_usage_threshold_percent +
|
||||
options_.high_encode_usage_threshold_percent) / 2.0f;
|
||||
}
|
||||
|
||||
float InitialEncodeTimeMs() const {
|
||||
return InitialUsageInPercent() * kInitialSampleDiffMs / 100;
|
||||
}
|
||||
|
||||
private:
|
||||
const float kWeightFactorFrameDiff;
|
||||
const float kWeightFactorEncodeTime;
|
||||
const float kInitialSampleDiffMs;
|
||||
const float kMaxSampleDiffMs;
|
||||
uint64_t count_;
|
||||
CpuOveruseOptions options_;
|
||||
scoped_ptr<VCMExpFilter> filtered_encode_time_ms_;
|
||||
scoped_ptr<VCMExpFilter> filtered_frame_diff_ms_;
|
||||
};
|
||||
@ -265,6 +298,7 @@ void OveruseFrameDetector::SetOptions(const CpuOveruseOptions& options) {
|
||||
}
|
||||
options_ = options;
|
||||
capture_deltas_.SetOptions(options);
|
||||
encode_usage_->SetOptions(options);
|
||||
ResetAll(num_pixels_);
|
||||
}
|
||||
|
||||
@ -315,6 +349,7 @@ bool OveruseFrameDetector::FrameTimeoutDetected(int64_t now) const {
|
||||
void OveruseFrameDetector::ResetAll(int num_pixels) {
|
||||
num_pixels_ = num_pixels;
|
||||
capture_deltas_.Reset();
|
||||
encode_usage_->Reset();
|
||||
capture_queue_delay_->ClearFrames();
|
||||
last_capture_time_ = 0;
|
||||
num_process_times_ = 0;
|
||||
@ -420,8 +455,15 @@ int32_t OveruseFrameDetector::Process() {
|
||||
}
|
||||
|
||||
bool OveruseFrameDetector::IsOverusing() {
|
||||
bool overusing = options_.enable_capture_jitter_method &&
|
||||
(capture_deltas_.StdDev() >= options_.high_capture_jitter_threshold_ms);
|
||||
bool overusing = false;
|
||||
if (options_.enable_capture_jitter_method) {
|
||||
overusing = capture_deltas_.StdDev() >=
|
||||
options_.high_capture_jitter_threshold_ms;
|
||||
} else if (options_.enable_encode_usage_method) {
|
||||
overusing = encode_usage_->UsageInPercent() >=
|
||||
options_.high_encode_usage_threshold_percent;
|
||||
}
|
||||
|
||||
if (overusing) {
|
||||
++checks_above_threshold_;
|
||||
} else {
|
||||
@ -435,8 +477,14 @@ bool OveruseFrameDetector::IsUnderusing(int64_t time_now) {
|
||||
if (time_now < last_rampup_time_ + delay)
|
||||
return false;
|
||||
|
||||
bool underusing = options_.enable_capture_jitter_method &&
|
||||
(capture_deltas_.StdDev() < options_.low_capture_jitter_threshold_ms);
|
||||
bool underusing = false;
|
||||
if (options_.enable_capture_jitter_method) {
|
||||
underusing = capture_deltas_.StdDev() <
|
||||
options_.low_capture_jitter_threshold_ms;
|
||||
} else if (options_.enable_encode_usage_method) {
|
||||
underusing = encode_usage_->UsageInPercent() <
|
||||
options_.low_encode_usage_threshold_percent;
|
||||
}
|
||||
return underusing;
|
||||
}
|
||||
} // namespace webrtc
|
||||
|
@ -66,6 +66,11 @@ class OveruseFrameDetectorTest : public ::testing::Test {
|
||||
options_.high_capture_jitter_threshold_ms) / 2.0f) + 0.5;
|
||||
}
|
||||
|
||||
int InitialEncodeUsage() {
|
||||
return ((options_.low_encode_usage_threshold_percent +
|
||||
options_.high_encode_usage_threshold_percent) / 2.0f) + 0.5;
|
||||
}
|
||||
|
||||
void InsertFramesWithInterval(
|
||||
size_t num_frames, int interval_ms, int width, int height) {
|
||||
while (num_frames-- > 0) {
|
||||
@ -74,6 +79,16 @@ class OveruseFrameDetectorTest : public ::testing::Test {
|
||||
}
|
||||
}
|
||||
|
||||
void InsertAndEncodeFramesWithInterval(
|
||||
int num_frames, int interval_ms, int width, int height, int encode_ms) {
|
||||
while (num_frames-- > 0) {
|
||||
overuse_detector_->FrameCaptured(width, height);
|
||||
clock_->AdvanceTimeMilliseconds(encode_ms);
|
||||
overuse_detector_->FrameEncoded(encode_ms);
|
||||
clock_->AdvanceTimeMilliseconds(interval_ms - encode_ms);
|
||||
}
|
||||
}
|
||||
|
||||
void TriggerOveruse(int num_times) {
|
||||
for (int i = 0; i < num_times; ++i) {
|
||||
InsertFramesWithInterval(200, kFrameInterval33ms, kWidth, kHeight);
|
||||
@ -87,6 +102,22 @@ class OveruseFrameDetectorTest : public ::testing::Test {
|
||||
overuse_detector_->Process();
|
||||
}
|
||||
|
||||
void TriggerOveruseWithEncodeUsage(int num_times) {
|
||||
const int kEncodeTimeMs = 32;
|
||||
for (int i = 0; i < num_times; ++i) {
|
||||
InsertAndEncodeFramesWithInterval(
|
||||
1000, kFrameInterval33ms, kWidth, kHeight, kEncodeTimeMs);
|
||||
overuse_detector_->Process();
|
||||
}
|
||||
}
|
||||
|
||||
void TriggerNormalUsageWithEncodeUsage() {
|
||||
const int kEncodeTimeMs = 5;
|
||||
InsertAndEncodeFramesWithInterval(
|
||||
1000, kFrameInterval33ms, kWidth, kHeight, kEncodeTimeMs);
|
||||
overuse_detector_->Process();
|
||||
}
|
||||
|
||||
CpuOveruseOptions options_;
|
||||
scoped_ptr<SimulatedClock> clock_;
|
||||
scoped_ptr<MockCpuOveruseObserver> observer_;
|
||||
@ -266,13 +297,42 @@ TEST_F(OveruseFrameDetectorTest, EncodedFrame) {
|
||||
EXPECT_EQ(2, overuse_detector_->AvgEncodeTimeMs());
|
||||
}
|
||||
|
||||
TEST_F(OveruseFrameDetectorTest, InitialEncodeUsage) {
|
||||
EXPECT_EQ(InitialEncodeUsage(), overuse_detector_->EncodeUsagePercent());
|
||||
}
|
||||
|
||||
TEST_F(OveruseFrameDetectorTest, EncodedUsage) {
|
||||
for (int i = 0; i < 30; i++) {
|
||||
overuse_detector_->FrameCaptured(kWidth, kHeight);
|
||||
clock_->AdvanceTimeMilliseconds(5);
|
||||
overuse_detector_->FrameEncoded(5);
|
||||
clock_->AdvanceTimeMilliseconds(33-5);
|
||||
}
|
||||
const int kEncodeTimeMs = 5;
|
||||
InsertAndEncodeFramesWithInterval(
|
||||
1000, kFrameInterval33ms, kWidth, kHeight, kEncodeTimeMs);
|
||||
EXPECT_EQ(15, overuse_detector_->EncodeUsagePercent());
|
||||
}
|
||||
|
||||
TEST_F(OveruseFrameDetectorTest, EncodeUsageResetAfterChangingThreshold) {
|
||||
EXPECT_EQ(InitialEncodeUsage(), overuse_detector_->EncodeUsagePercent());
|
||||
options_.high_encode_usage_threshold_percent = 100;
|
||||
overuse_detector_->SetOptions(options_);
|
||||
EXPECT_EQ(InitialEncodeUsage(), overuse_detector_->EncodeUsagePercent());
|
||||
options_.low_encode_usage_threshold_percent = 20;
|
||||
overuse_detector_->SetOptions(options_);
|
||||
EXPECT_EQ(InitialEncodeUsage(), overuse_detector_->EncodeUsagePercent());
|
||||
}
|
||||
|
||||
TEST_F(OveruseFrameDetectorTest, TriggerOveruseWithEncodeUsage) {
|
||||
options_.enable_capture_jitter_method = false;
|
||||
options_.enable_encode_usage_method = true;
|
||||
overuse_detector_->SetOptions(options_);
|
||||
EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(1);
|
||||
TriggerOveruseWithEncodeUsage(options_.high_threshold_consecutive_count);
|
||||
}
|
||||
|
||||
TEST_F(OveruseFrameDetectorTest, OveruseAndRecoverWithEncodeUsage) {
|
||||
options_.enable_capture_jitter_method = false;
|
||||
options_.enable_encode_usage_method = true;
|
||||
overuse_detector_->SetOptions(options_);
|
||||
EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(1);
|
||||
TriggerOveruseWithEncodeUsage(options_.high_threshold_consecutive_count);
|
||||
EXPECT_CALL(*(observer_.get()), NormalUsage()).Times(testing::AtLeast(1));
|
||||
TriggerNormalUsageWithEncodeUsage();
|
||||
}
|
||||
} // namespace webrtc
|
||||
|
Loading…
x
Reference in New Issue
Block a user