Added api for getting cpu measures using a struct.

R=mflodman@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/12479004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@6249 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
asapersson@webrtc.org 2014-05-27 07:43:15 +00:00
parent 74767401f2
commit ab6bf4f54c
8 changed files with 129 additions and 84 deletions

View File

@ -109,6 +109,24 @@ struct CpuOveruseOptions {
}
};
struct CpuOveruseMetrics {
CpuOveruseMetrics()
: capture_jitter_ms(-1),
avg_encode_time_ms(-1),
encode_usage_percent(-1),
capture_queue_delay_ms_per_s(-1) {}
int capture_jitter_ms; // The current estimated jitter in ms based on
// incoming captured frames.
int avg_encode_time_ms; // The average encode time in ms.
int encode_usage_percent; // The average encode time divided by the average
// time difference between incoming captured frames.
int capture_queue_delay_ms_per_s; // The current time delay between an
// incoming captured frame until the frame
// is being processed. The delay is
// expressed in ms delay per second.
};
class WEBRTC_DLLEXPORT VideoEngine {
public:
// Creates a VideoEngine object, which can then be used to acquire subAPIs.
@ -193,16 +211,12 @@ class WEBRTC_DLLEXPORT ViEBase {
}
// Gets cpu overuse measures.
// capture_jitter_ms: The current estimated jitter in ms based on incoming
// captured frames.
// avg_encode_time_ms: The average encode time in ms.
// encode_usage_percent: The average encode time divided by the average time
// difference between incoming captured frames.
// capture_queue_delay_ms_per_s: The current time delay between an incoming
// captured frame until the frame is being
// processed. The delay is expressed in ms
// delay per second.
// TODO(asapersson): Remove default implementation.
virtual int GetCpuOveruseMetrics(int channel,
CpuOveruseMetrics* metrics) {
return -1;
}
// TODO(asapersson): Remove this function when libjingle has been updated.
virtual int CpuOveruseMeasures(int channel,
int* capture_jitter_ms,
int* avg_encode_time_ms,

View File

@ -302,31 +302,21 @@ void OveruseFrameDetector::SetOptions(const CpuOveruseOptions& options) {
ResetAll(num_pixels_);
}
int OveruseFrameDetector::CaptureJitterMs() const {
CriticalSectionScoped cs(crit_.get());
return static_cast<int>(capture_deltas_.StdDev() + 0.5);
}
int OveruseFrameDetector::AvgEncodeTimeMs() const {
CriticalSectionScoped cs(crit_.get());
return encode_time_->filtered_encode_time_ms();
}
int OveruseFrameDetector::EncodeUsagePercent() const {
CriticalSectionScoped cs(crit_.get());
return encode_usage_->UsageInPercent();
}
int OveruseFrameDetector::AvgCaptureQueueDelayMsPerS() const {
CriticalSectionScoped cs(crit_.get());
return capture_queue_delay_->filtered_delay_ms_per_s();
}
int OveruseFrameDetector::CaptureQueueDelayMsPerS() const {
CriticalSectionScoped cs(crit_.get());
return capture_queue_delay_->delay_ms();
}
void OveruseFrameDetector::GetCpuOveruseMetrics(
CpuOveruseMetrics* metrics) const {
CriticalSectionScoped cs(crit_.get());
metrics->capture_jitter_ms = static_cast<int>(capture_deltas_.StdDev() + 0.5);
metrics->avg_encode_time_ms = encode_time_->filtered_encode_time_ms();
metrics->encode_usage_percent = encode_usage_->UsageInPercent();
metrics->capture_queue_delay_ms_per_s =
capture_queue_delay_->filtered_delay_ms_per_s();
}
int32_t OveruseFrameDetector::TimeUntilNextProcess() {
CriticalSectionScoped cs(crit_.get());
return next_process_time_ - clock_->TimeInMilliseconds();

View File

@ -70,25 +70,23 @@ class OveruseFrameDetector : public Module {
void FrameEncoded(int encode_time_ms);
// Accessors.
// The estimated jitter based on incoming captured frames.
int CaptureJitterMs() const;
// Running average of reported encode time (FrameEncoded()).
// Only used for stats.
int AvgEncodeTimeMs() const;
// Returns CpuOveruseMetrics where
// capture_jitter_ms: The estimated jitter based on incoming captured frames.
// avg_encode_time_ms: Running average of reported encode time
// (FrameEncoded()). Only used for stats.
// encode_usage_percent: The average encode time divided by the average time
// difference between incoming captured frames.
// capture_queue_delay_ms_per_s: The current time delay between an incoming
// captured frame (FrameCaptured()) until the
// frame is being processed
// (FrameProcessingStarted()). (Note: if a new
// frame is received before an old frame has
// been processed, the old frame is skipped).
// The delay is expressed in ms delay per sec.
// Only used for stats.
void GetCpuOveruseMetrics(CpuOveruseMetrics* metrics) const;
// The average encode time divided by the average time difference between
// incoming captured frames.
// This variable is currently only used for statistics.
int EncodeUsagePercent() const;
// The current time delay between an incoming captured frame (FrameCaptured())
// until the frame is being processed (FrameProcessingStarted()).
// (Note: if a new frame is received before an old frame has been processed,
// the old frame is skipped).
// The delay is returned as the delay in ms per second.
// This variable is currently only used for statistics.
int AvgCaptureQueueDelayMsPerS() const;
int CaptureQueueDelayMsPerS() const;
// Implements Module.

View File

@ -118,6 +118,24 @@ class OveruseFrameDetectorTest : public ::testing::Test {
overuse_detector_->Process();
}
int CaptureJitterMs() {
CpuOveruseMetrics metrics;
overuse_detector_->GetCpuOveruseMetrics(&metrics);
return metrics.capture_jitter_ms;
}
int AvgEncodeTimeMs() {
CpuOveruseMetrics metrics;
overuse_detector_->GetCpuOveruseMetrics(&metrics);
return metrics.avg_encode_time_ms;
}
int EncodeUsagePercent() {
CpuOveruseMetrics metrics;
overuse_detector_->GetCpuOveruseMetrics(&metrics);
return metrics.encode_usage_percent;
}
CpuOveruseOptions options_;
scoped_ptr<SimulatedClock> clock_;
scoped_ptr<MockCpuOveruseObserver> observer_;
@ -196,49 +214,58 @@ TEST_F(OveruseFrameDetectorTest, IncorrectConsecutiveCountTriggersNoOveruse) {
TriggerOveruse(1);
}
TEST_F(OveruseFrameDetectorTest, GetCpuOveruseMetrics) {
CpuOveruseMetrics metrics;
overuse_detector_->GetCpuOveruseMetrics(&metrics);
EXPECT_GT(metrics.capture_jitter_ms, 0);
EXPECT_GT(metrics.avg_encode_time_ms, 0);
EXPECT_GT(metrics.encode_usage_percent, 0);
EXPECT_GE(metrics.capture_queue_delay_ms_per_s, 0);
}
TEST_F(OveruseFrameDetectorTest, CaptureJitter) {
EXPECT_EQ(InitialJitter(), overuse_detector_->CaptureJitterMs());
EXPECT_EQ(InitialJitter(), CaptureJitterMs());
InsertFramesWithInterval(1000, kFrameInterval33ms, kWidth, kHeight);
EXPECT_NE(InitialJitter(), overuse_detector_->CaptureJitterMs());
EXPECT_NE(InitialJitter(), CaptureJitterMs());
}
TEST_F(OveruseFrameDetectorTest, CaptureJitterResetAfterResolutionChange) {
EXPECT_EQ(InitialJitter(), overuse_detector_->CaptureJitterMs());
EXPECT_EQ(InitialJitter(), CaptureJitterMs());
InsertFramesWithInterval(1000, kFrameInterval33ms, kWidth, kHeight);
EXPECT_NE(InitialJitter(), overuse_detector_->CaptureJitterMs());
EXPECT_NE(InitialJitter(), CaptureJitterMs());
// Verify reset.
InsertFramesWithInterval(1, kFrameInterval33ms, kWidth, kHeight + 1);
EXPECT_EQ(InitialJitter(), overuse_detector_->CaptureJitterMs());
EXPECT_EQ(InitialJitter(), CaptureJitterMs());
}
TEST_F(OveruseFrameDetectorTest, CaptureJitterResetAfterFrameTimeout) {
EXPECT_EQ(InitialJitter(), overuse_detector_->CaptureJitterMs());
EXPECT_EQ(InitialJitter(), CaptureJitterMs());
InsertFramesWithInterval(1000, kFrameInterval33ms, kWidth, kHeight);
EXPECT_NE(InitialJitter(), overuse_detector_->CaptureJitterMs());
EXPECT_NE(InitialJitter(), CaptureJitterMs());
InsertFramesWithInterval(
1, options_.frame_timeout_interval_ms, kWidth, kHeight);
EXPECT_NE(InitialJitter(), overuse_detector_->CaptureJitterMs());
EXPECT_NE(InitialJitter(), CaptureJitterMs());
// Verify reset.
InsertFramesWithInterval(
1, options_.frame_timeout_interval_ms + 1, kWidth, kHeight);
EXPECT_EQ(InitialJitter(), overuse_detector_->CaptureJitterMs());
EXPECT_EQ(InitialJitter(), CaptureJitterMs());
}
TEST_F(OveruseFrameDetectorTest, CaptureJitterResetAfterChangingThreshold) {
EXPECT_EQ(InitialJitter(), overuse_detector_->CaptureJitterMs());
EXPECT_EQ(InitialJitter(), CaptureJitterMs());
options_.high_capture_jitter_threshold_ms = 90.0f;
overuse_detector_->SetOptions(options_);
EXPECT_EQ(InitialJitter(), overuse_detector_->CaptureJitterMs());
EXPECT_EQ(InitialJitter(), CaptureJitterMs());
options_.low_capture_jitter_threshold_ms = 30.0f;
overuse_detector_->SetOptions(options_);
EXPECT_EQ(InitialJitter(), overuse_detector_->CaptureJitterMs());
EXPECT_EQ(InitialJitter(), CaptureJitterMs());
}
TEST_F(OveruseFrameDetectorTest, MinFrameSamplesBeforeUpdatingCaptureJitter) {
options_.min_frame_samples = 40;
overuse_detector_->SetOptions(options_);
InsertFramesWithInterval(40, kFrameInterval33ms, kWidth, kHeight);
EXPECT_EQ(InitialJitter(), overuse_detector_->CaptureJitterMs());
EXPECT_EQ(InitialJitter(), CaptureJitterMs());
}
TEST_F(OveruseFrameDetectorTest, NoCaptureQueueDelay) {
@ -289,33 +316,33 @@ TEST_F(OveruseFrameDetectorTest, CaptureQueueDelayNoMatchingCapturedFrame) {
TEST_F(OveruseFrameDetectorTest, EncodedFrame) {
const int kInitialAvgEncodeTimeInMs = 5;
EXPECT_EQ(kInitialAvgEncodeTimeInMs, overuse_detector_->AvgEncodeTimeMs());
EXPECT_EQ(kInitialAvgEncodeTimeInMs, AvgEncodeTimeMs());
for (int i = 0; i < 30; i++) {
clock_->AdvanceTimeMilliseconds(33);
overuse_detector_->FrameEncoded(2);
}
EXPECT_EQ(2, overuse_detector_->AvgEncodeTimeMs());
EXPECT_EQ(2, AvgEncodeTimeMs());
}
TEST_F(OveruseFrameDetectorTest, InitialEncodeUsage) {
EXPECT_EQ(InitialEncodeUsage(), overuse_detector_->EncodeUsagePercent());
EXPECT_EQ(InitialEncodeUsage(), EncodeUsagePercent());
}
TEST_F(OveruseFrameDetectorTest, EncodedUsage) {
const int kEncodeTimeMs = 5;
InsertAndEncodeFramesWithInterval(
1000, kFrameInterval33ms, kWidth, kHeight, kEncodeTimeMs);
EXPECT_EQ(15, overuse_detector_->EncodeUsagePercent());
EXPECT_EQ(15, EncodeUsagePercent());
}
TEST_F(OveruseFrameDetectorTest, EncodeUsageResetAfterChangingThreshold) {
EXPECT_EQ(InitialEncodeUsage(), overuse_detector_->EncodeUsagePercent());
EXPECT_EQ(InitialEncodeUsage(), EncodeUsagePercent());
options_.high_encode_usage_threshold_percent = 100;
overuse_detector_->SetOptions(options_);
EXPECT_EQ(InitialEncodeUsage(), overuse_detector_->EncodeUsagePercent());
EXPECT_EQ(InitialEncodeUsage(), EncodeUsagePercent());
options_.low_encode_usage_threshold_percent = 20;
overuse_detector_->SetOptions(options_);
EXPECT_EQ(InitialEncodeUsage(), overuse_detector_->EncodeUsagePercent());
EXPECT_EQ(InitialEncodeUsage(), EncodeUsagePercent());
}
TEST_F(OveruseFrameDetectorTest, TriggerOveruseWithEncodeUsage) {

View File

@ -140,10 +140,35 @@ int ViEBaseImpl::CpuOveruseMeasures(int video_channel,
if (provider) {
ViECapturer* capturer = is.Capture(provider->Id());
if (capturer) {
capturer->CpuOveruseMeasures(capture_jitter_ms,
avg_encode_time_ms,
encode_usage_percent,
capture_queue_delay_ms_per_s);
CpuOveruseMetrics metrics;
capturer->GetCpuOveruseMetrics(&metrics);
*capture_jitter_ms = metrics.capture_jitter_ms;
*avg_encode_time_ms = metrics.avg_encode_time_ms;
*encode_usage_percent = metrics.encode_usage_percent;
*capture_queue_delay_ms_per_s = metrics.capture_queue_delay_ms_per_s;
return 0;
}
}
return -1;
}
int ViEBaseImpl::GetCpuOveruseMetrics(int video_channel,
CpuOveruseMetrics* metrics) {
ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
ViEChannel* vie_channel = cs.Channel(video_channel);
if (!vie_channel) {
shared_data_.SetLastError(kViEBaseInvalidChannelId);
return -1;
}
ViEEncoder* vie_encoder = cs.Encoder(video_channel);
assert(vie_encoder);
ViEInputManagerScoped is(*(shared_data_.input_manager()));
ViEFrameProviderBase* provider = is.FrameProvider(vie_encoder);
if (provider) {
ViECapturer* capturer = is.Capture(provider->Id());
if (capturer) {
capturer->GetCpuOveruseMetrics(metrics);
return 0;
}
}

View File

@ -35,6 +35,8 @@ class ViEBaseImpl
CpuOveruseObserver* observer);
virtual int SetCpuOveruseOptions(int channel,
const CpuOveruseOptions& options);
virtual int GetCpuOveruseMetrics(int channel,
CpuOveruseMetrics* metrics);
virtual int CpuOveruseMeasures(int channel,
int* capture_jitter_ms,
int* avg_encode_time_ms,

View File

@ -249,15 +249,8 @@ void ViECapturer::SetCpuOveruseOptions(const CpuOveruseOptions& options) {
overuse_detector_->SetOptions(options);
}
void ViECapturer::CpuOveruseMeasures(int* capture_jitter_ms,
int* avg_encode_time_ms,
int* encode_usage_percent,
int* capture_queue_delay_ms_per_s) const {
*capture_jitter_ms = overuse_detector_->CaptureJitterMs();
*avg_encode_time_ms = overuse_detector_->AvgEncodeTimeMs();
*encode_usage_percent = overuse_detector_->EncodeUsagePercent();
*capture_queue_delay_ms_per_s =
overuse_detector_->AvgCaptureQueueDelayMsPerS();
void ViECapturer::GetCpuOveruseMetrics(CpuOveruseMetrics* metrics) const {
overuse_detector_->GetCpuOveruseMetrics(metrics);
}
int32_t ViECapturer::SetCaptureDelay(int32_t delay_ms) {

View File

@ -108,11 +108,7 @@ class ViECapturer
void RegisterCpuOveruseObserver(CpuOveruseObserver* observer);
void SetCpuOveruseOptions(const CpuOveruseOptions& options);
void CpuOveruseMeasures(int* capture_jitter_ms,
int* avg_encode_time_ms,
int* encode_usage_percent,
int* capture_queue_delay_ms_per_s) const;
void GetCpuOveruseMetrics(CpuOveruseMetrics* metrics) const;
protected:
ViECapturer(int capture_id,