From e6168f5f4100d0fb498bd1c17980986fd657b75d Mon Sep 17 00:00:00 2001 From: "mflodman@webrtc.org" Date: Wed, 26 Jun 2013 11:23:01 +0000 Subject: [PATCH] Adding a first simple version of overuse detection, but not hooked up. BUG= R=asapersson@webrtc.org Review URL: https://webrtc-codereview.appspot.com/1717004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@4268 4adac7df-926f-26a2-2b94-8c16560cd09d --- webrtc/video_engine/overuse_frame_detector.cc | 82 +++++++++++++++++++ webrtc/video_engine/overuse_frame_detector.h | 73 +++++++++++++++++ .../overuse_frame_detector_unittest.cc | 66 +++++++++++++++ webrtc/video_engine/video_engine_core.gypi | 3 + 4 files changed, 224 insertions(+) create mode 100644 webrtc/video_engine/overuse_frame_detector.cc create mode 100644 webrtc/video_engine/overuse_frame_detector.h create mode 100644 webrtc/video_engine/overuse_frame_detector_unittest.cc diff --git a/webrtc/video_engine/overuse_frame_detector.cc b/webrtc/video_engine/overuse_frame_detector.cc new file mode 100644 index 000000000..a373c9a63 --- /dev/null +++ b/webrtc/video_engine/overuse_frame_detector.cc @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "webrtc/video_engine/overuse_frame_detector.h" + +#include + +#include "webrtc/system_wrappers/interface/clock.h" +#include "webrtc/system_wrappers/interface/critical_section_wrapper.h" + +namespace webrtc { + +// TODO(mflodman) Test different thresholds. +const int64_t kProcessIntervalMs = 2000; +const int kOveruseHistoryMs = 5000; +const float kMinEncodeRatio = 29 / 30.0f; + +OveruseFrameDetector::OveruseFrameDetector(Clock* clock, + OveruseObserver* observer) + : crit_(CriticalSectionWrapper::CreateCriticalSection()), + observer_(observer), + clock_(clock), + last_process_time_(clock->TimeInMilliseconds()) { + assert(observer); +} + +OveruseFrameDetector::~OveruseFrameDetector() { +} + +void OveruseFrameDetector::CapturedFrame() { + CriticalSectionScoped cs(crit_.get()); + CleanOldSamples(); + capture_times_.push_back(clock_->TimeInMilliseconds()); +} + +void OveruseFrameDetector::EncodedFrame() { + CriticalSectionScoped cs(crit_.get()); + encode_times_.push_back(clock_->TimeInMilliseconds()); +} + +int32_t OveruseFrameDetector::TimeUntilNextProcess() { + return last_process_time_ + kProcessIntervalMs - clock_->TimeInMilliseconds(); +} + +int32_t OveruseFrameDetector::Process() { + CriticalSectionScoped cs(crit_.get()); + if (clock_->TimeInMilliseconds() < last_process_time_ + kProcessIntervalMs) + return 0; + + last_process_time_ = clock_->TimeInMilliseconds(); + CleanOldSamples(); + + if (encode_times_.size() == 0 || capture_times_.size() == 0) + return 0; + + float encode_ratio = encode_times_.size() / + static_cast(capture_times_.size()); + if (encode_ratio < kMinEncodeRatio) { + observer_->OveruseDetected(); + } + return 0; +} + +void OveruseFrameDetector::CleanOldSamples() { + int64_t time_now = clock_->TimeInMilliseconds(); + while (capture_times_.size() > 0 && + capture_times_.front() < time_now - kOveruseHistoryMs) { + capture_times_.pop_front(); + } + while (encode_times_.size() > 0 && + encode_times_.front() < time_now - kOveruseHistoryMs) { + encode_times_.pop_front(); + } +} +} // namespace webrtc diff --git a/webrtc/video_engine/overuse_frame_detector.h b/webrtc/video_engine/overuse_frame_detector.h new file mode 100644 index 000000000..d631d34ac --- /dev/null +++ b/webrtc/video_engine/overuse_frame_detector.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_VIDEO_ENGINE_OVERUSE_FRAME_DETECTOR_H_ +#define WEBRTC_VIDEO_ENGINE_OVERUSE_FRAME_DETECTOR_H_ + +#include + +#include "webrtc/modules/interface/module.h" +#include "webrtc/system_wrappers/interface/constructor_magic.h" +#include "webrtc/system_wrappers/interface/scoped_ptr.h" + +namespace webrtc { + +class Clock; +class CriticalSectionWrapper; + +class OveruseObserver { + public: + // Called when an overuse has been detected, based on the number of calls to + // 'CapturedFrame' and 'EncodedFrame'. + virtual void OveruseDetected() = 0; + virtual ~OveruseObserver() {} +}; + +// Use to detect system overuse based on the number of captured frames vs. the +// number of encoded frames. +class OveruseFrameDetector : public Module { + public: + OveruseFrameDetector(Clock* clock, OveruseObserver* observer); + ~OveruseFrameDetector(); + + // Called for each new captured frame. + void CapturedFrame(); + + // Called for every encoded frame. + void EncodedFrame(); + + // Implements Module. + virtual int32_t TimeUntilNextProcess(); + virtual int32_t Process(); + + private: + void CleanOldSamples(); + + // Protecting all members. + scoped_ptr crit_; + + // Observer getting overuse reports. + OveruseObserver* observer_; + + Clock* clock_; + int64_t last_process_time_; + + // Capture time for frames. + std::list capture_times_; + + // Start encode time for a frame. + std::list encode_times_; + + DISALLOW_COPY_AND_ASSIGN(OveruseFrameDetector); +}; + +} // namespace webrtc + +#endif // WEBRTC_VIDEO_ENGINE_OVERUSE_FRAME_DETECTOR_H_ diff --git a/webrtc/video_engine/overuse_frame_detector_unittest.cc b/webrtc/video_engine/overuse_frame_detector_unittest.cc new file mode 100644 index 000000000..383f80f4b --- /dev/null +++ b/webrtc/video_engine/overuse_frame_detector_unittest.cc @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +#include "webrtc/system_wrappers/interface/clock.h" +#include "webrtc/system_wrappers/interface/scoped_ptr.h" +#include "webrtc/video_engine/overuse_frame_detector.h" + +using ::testing::_; +using ::testing::AnyNumber; +using ::testing::Return; + +namespace webrtc { + +const int kProcessIntervalMs = 2000; + +class MockOveruseObserver : public OveruseObserver { + public: + MockOveruseObserver() {} + virtual ~MockOveruseObserver() {} + + MOCK_METHOD0(OveruseDetected, void()); +}; + +class OveruseFrameDetectorTest : public ::testing::Test { + protected: + virtual void SetUp() { + clock_.reset(new SimulatedClock(1234)); + observer_.reset(new MockOveruseObserver()); + overuse_detector_.reset(new OveruseFrameDetector(clock_.get(), + observer_.get())); + } + scoped_ptr clock_; + scoped_ptr observer_; + scoped_ptr overuse_detector_; +}; + +TEST_F(OveruseFrameDetectorTest, TriggerOveruse) { + EXPECT_EQ(overuse_detector_->TimeUntilNextProcess(), kProcessIntervalMs); + overuse_detector_->CapturedFrame(); + overuse_detector_->EncodedFrame(); + clock_->AdvanceTimeMilliseconds(kProcessIntervalMs); + EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(0); + overuse_detector_->Process(); + + overuse_detector_->CapturedFrame(); + clock_->AdvanceTimeMilliseconds(kProcessIntervalMs); + EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(1); + overuse_detector_->Process(); + + clock_->AdvanceTimeMilliseconds(5000); + overuse_detector_->CapturedFrame(); + overuse_detector_->EncodedFrame(); + EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(0); + overuse_detector_->Process(); +} +} // namespace webrtc diff --git a/webrtc/video_engine/video_engine_core.gypi b/webrtc/video_engine/video_engine_core.gypi index d0a75987f..629f0a2b7 100644 --- a/webrtc/video_engine/video_engine_core.gypi +++ b/webrtc/video_engine/video_engine_core.gypi @@ -50,6 +50,7 @@ # headers 'call_stats.h', 'encoder_state_feedback.h', + 'overuse_frame_detector.h', 'stream_synchronization.h', 'vie_base_impl.h', 'vie_capture_impl.h', @@ -83,6 +84,7 @@ # ViE 'call_stats.cc', 'encoder_state_feedback.cc', + 'overuse_frame_detector.cc', 'stream_synchronization.cc', 'vie_base_impl.cc', 'vie_capture_impl.cc', @@ -152,6 +154,7 @@ 'sources': [ 'call_stats_unittest.cc', 'encoder_state_feedback_unittest.cc', + 'overuse_frame_detector_unittest.cc', 'stream_synchronization_unittest.cc', 'vie_remb_unittest.cc', ],