Refactor OveruseFrameDetector to use timing in us units
Use rtc::TimeMicros, and don't refer to ntp time. BUG=webrtc:6977 Review-Url: https://codereview.webrtc.org/2633673002 Cr-Commit-Position: refs/heads/master@{#16138}
This commit is contained in:
parent
d3fabe51b2
commit
e0e3bdfbbf
@ -285,6 +285,7 @@ if (!build_with_chromium) {
|
||||
":webrtc_nonparallel_tests",
|
||||
":webrtc_perf_tests",
|
||||
"api:peerconnection_unittests",
|
||||
"base:rtc_base_tests_utils",
|
||||
"common_audio:common_audio_unittests",
|
||||
"common_video:common_video_unittests",
|
||||
"media:rtc_media_unittests",
|
||||
@ -406,6 +407,7 @@ if (rtc_include_tests) {
|
||||
testonly = true
|
||||
deps = [
|
||||
"audio:audio_tests",
|
||||
"base:rtc_base_tests_utils",
|
||||
"call:call_tests",
|
||||
"modules/video_capture",
|
||||
"test:test_common",
|
||||
|
||||
@ -22,7 +22,6 @@
|
||||
#include "webrtc/base/logging.h"
|
||||
#include "webrtc/base/numerics/exp_filter.h"
|
||||
#include "webrtc/common_video/include/frame_callback.h"
|
||||
#include "webrtc/system_wrappers/include/clock.h"
|
||||
|
||||
#if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
|
||||
#include <mach/mach.h>
|
||||
@ -203,7 +202,6 @@ class OveruseFrameDetector::CheckOveruseTask : public rtc::QueuedTask {
|
||||
};
|
||||
|
||||
OveruseFrameDetector::OveruseFrameDetector(
|
||||
Clock* clock,
|
||||
const CpuOveruseOptions& options,
|
||||
ScalingObserverInterface* observer,
|
||||
EncodedFrameObserver* encoder_timing,
|
||||
@ -213,10 +211,10 @@ OveruseFrameDetector::OveruseFrameDetector(
|
||||
observer_(observer),
|
||||
encoder_timing_(encoder_timing),
|
||||
metrics_observer_(metrics_observer),
|
||||
clock_(clock),
|
||||
num_process_times_(0),
|
||||
last_capture_time_ms_(-1),
|
||||
last_processed_capture_time_ms_(-1),
|
||||
// TODO(nisse): Use rtc::Optional
|
||||
last_capture_time_us_(-1),
|
||||
last_processed_capture_time_us_(-1),
|
||||
num_pixels_(0),
|
||||
last_overuse_time_ms_(-1),
|
||||
checks_above_threshold_(0),
|
||||
@ -260,11 +258,12 @@ bool OveruseFrameDetector::FrameSizeChanged(int num_pixels) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool OveruseFrameDetector::FrameTimeoutDetected(int64_t now) const {
|
||||
bool OveruseFrameDetector::FrameTimeoutDetected(int64_t now_us) const {
|
||||
RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_);
|
||||
if (last_capture_time_ms_ == -1)
|
||||
if (last_capture_time_us_ == -1)
|
||||
return false;
|
||||
return (now - last_capture_time_ms_) > options_.frame_timeout_interval_ms;
|
||||
return (now_us - last_capture_time_us_) >
|
||||
options_.frame_timeout_interval_ms * rtc::kNumMicrosecsPerMillisec;
|
||||
}
|
||||
|
||||
void OveruseFrameDetector::ResetAll(int num_pixels) {
|
||||
@ -272,32 +271,33 @@ void OveruseFrameDetector::ResetAll(int num_pixels) {
|
||||
num_pixels_ = num_pixels;
|
||||
usage_->Reset();
|
||||
frame_timing_.clear();
|
||||
last_capture_time_ms_ = -1;
|
||||
last_processed_capture_time_ms_ = -1;
|
||||
last_capture_time_us_ = -1;
|
||||
last_processed_capture_time_us_ = -1;
|
||||
num_process_times_ = 0;
|
||||
metrics_ = rtc::Optional<CpuOveruseMetrics>();
|
||||
}
|
||||
|
||||
void OveruseFrameDetector::FrameCaptured(const VideoFrame& frame,
|
||||
int64_t time_when_first_seen_ms) {
|
||||
int64_t time_when_first_seen_us) {
|
||||
RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_);
|
||||
|
||||
if (FrameSizeChanged(frame.width() * frame.height()) ||
|
||||
FrameTimeoutDetected(time_when_first_seen_ms)) {
|
||||
FrameTimeoutDetected(time_when_first_seen_us)) {
|
||||
ResetAll(frame.width() * frame.height());
|
||||
}
|
||||
|
||||
if (last_capture_time_ms_ != -1)
|
||||
usage_->AddCaptureSample(time_when_first_seen_ms - last_capture_time_ms_);
|
||||
if (last_capture_time_us_ != -1)
|
||||
usage_->AddCaptureSample(
|
||||
1e-3 * (time_when_first_seen_us - last_capture_time_us_));
|
||||
|
||||
last_capture_time_ms_ = time_when_first_seen_ms;
|
||||
last_capture_time_us_ = time_when_first_seen_us;
|
||||
|
||||
frame_timing_.push_back(FrameTiming(frame.ntp_time_ms(), frame.timestamp(),
|
||||
time_when_first_seen_ms));
|
||||
frame_timing_.push_back(FrameTiming(frame.timestamp_us(), frame.timestamp(),
|
||||
time_when_first_seen_us));
|
||||
}
|
||||
|
||||
void OveruseFrameDetector::FrameSent(uint32_t timestamp,
|
||||
int64_t time_sent_in_ms) {
|
||||
int64_t time_sent_in_us) {
|
||||
RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_);
|
||||
// Delay before reporting actual encoding time, used to have the ability to
|
||||
// detect total encoding time when encoding more than one layer. Encoding is
|
||||
@ -307,7 +307,7 @@ void OveruseFrameDetector::FrameSent(uint32_t timestamp,
|
||||
static const int64_t kEncodingTimeMeasureWindowMs = 1000;
|
||||
for (auto& it : frame_timing_) {
|
||||
if (it.timestamp == timestamp) {
|
||||
it.last_send_ms = time_sent_in_ms;
|
||||
it.last_send_us = time_sent_in_us;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -319,21 +319,26 @@ void OveruseFrameDetector::FrameSent(uint32_t timestamp,
|
||||
// https://crbug.com/350106
|
||||
while (!frame_timing_.empty()) {
|
||||
FrameTiming timing = frame_timing_.front();
|
||||
if (time_sent_in_ms - timing.capture_ms < kEncodingTimeMeasureWindowMs)
|
||||
if (time_sent_in_us - timing.capture_us <
|
||||
kEncodingTimeMeasureWindowMs * rtc::kNumMicrosecsPerMillisec)
|
||||
break;
|
||||
if (timing.last_send_ms != -1) {
|
||||
int encode_duration_ms =
|
||||
static_cast<int>(timing.last_send_ms - timing.capture_ms);
|
||||
if (timing.last_send_us != -1) {
|
||||
int encode_duration_us =
|
||||
static_cast<int>(timing.last_send_us - timing.capture_us);
|
||||
if (encoder_timing_) {
|
||||
encoder_timing_->OnEncodeTiming(timing.capture_ntp_ms,
|
||||
encode_duration_ms);
|
||||
// TODO(nisse): Update encoder_timing_ to also use us units.
|
||||
encoder_timing_->OnEncodeTiming(timing.capture_time_us /
|
||||
rtc::kNumMicrosecsPerMillisec,
|
||||
encode_duration_us /
|
||||
rtc::kNumMicrosecsPerMillisec);
|
||||
}
|
||||
if (last_processed_capture_time_ms_ != -1) {
|
||||
int64_t diff_ms = timing.capture_ms - last_processed_capture_time_ms_;
|
||||
usage_->AddSample(encode_duration_ms, diff_ms);
|
||||
if (last_processed_capture_time_us_ != -1) {
|
||||
int64_t diff_us = timing.capture_us - last_processed_capture_time_us_;
|
||||
usage_->AddSample(1e-3 * encode_duration_us, 1e-3 * diff_us);
|
||||
}
|
||||
last_processed_capture_time_ms_ = timing.capture_ms;
|
||||
EncodedFrameTimeMeasured(encode_duration_ms);
|
||||
last_processed_capture_time_us_ = timing.capture_us;
|
||||
EncodedFrameTimeMeasured(encode_duration_us /
|
||||
rtc::kNumMicrosecsPerMillisec);
|
||||
}
|
||||
frame_timing_.pop_front();
|
||||
}
|
||||
@ -345,7 +350,7 @@ void OveruseFrameDetector::CheckForOveruse() {
|
||||
if (num_process_times_ <= options_.min_process_count || !metrics_)
|
||||
return;
|
||||
|
||||
int64_t now = clock_->TimeInMilliseconds();
|
||||
int64_t now_ms = rtc::TimeMillis();
|
||||
|
||||
if (IsOverusing(*metrics_)) {
|
||||
// If the last thing we did was going up, and now have to back down, we need
|
||||
@ -353,7 +358,7 @@ void OveruseFrameDetector::CheckForOveruse() {
|
||||
// back and forth between this load, the system doesn't seem to handle it.
|
||||
bool check_for_backoff = last_rampup_time_ms_ > last_overuse_time_ms_;
|
||||
if (check_for_backoff) {
|
||||
if (now - last_rampup_time_ms_ < kStandardRampUpDelayMs ||
|
||||
if (now_ms - last_rampup_time_ms_ < kStandardRampUpDelayMs ||
|
||||
num_overuse_detections_ > kMaxOverusesBeforeApplyRampupDelay) {
|
||||
// Going up was not ok for very long, back off.
|
||||
current_rampup_delay_ms_ *= kRampUpBackoffFactor;
|
||||
@ -365,15 +370,15 @@ void OveruseFrameDetector::CheckForOveruse() {
|
||||
}
|
||||
}
|
||||
|
||||
last_overuse_time_ms_ = now;
|
||||
last_overuse_time_ms_ = now_ms;
|
||||
in_quick_rampup_ = false;
|
||||
checks_above_threshold_ = 0;
|
||||
++num_overuse_detections_;
|
||||
|
||||
if (observer_)
|
||||
observer_->ScaleDown(kScaleReasonCpu);
|
||||
} else if (IsUnderusing(*metrics_, now)) {
|
||||
last_rampup_time_ms_ = now;
|
||||
} else if (IsUnderusing(*metrics_, now_ms)) {
|
||||
last_rampup_time_ms_ = now_ms;
|
||||
in_quick_rampup_ = true;
|
||||
|
||||
if (observer_)
|
||||
|
||||
@ -24,7 +24,6 @@
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class Clock;
|
||||
class EncodedFrameObserver;
|
||||
class VideoFrame;
|
||||
|
||||
@ -65,8 +64,7 @@ class CpuOveruseMetricsObserver {
|
||||
// check for overuse.
|
||||
class OveruseFrameDetector {
|
||||
public:
|
||||
OveruseFrameDetector(Clock* clock,
|
||||
const CpuOveruseOptions& options,
|
||||
OveruseFrameDetector(const CpuOveruseOptions& options,
|
||||
ScalingObserverInterface* overuse_observer,
|
||||
EncodedFrameObserver* encoder_timing_,
|
||||
CpuOveruseMetricsObserver* metrics_observer);
|
||||
@ -80,10 +78,10 @@ class OveruseFrameDetector {
|
||||
void StopCheckForOveruse();
|
||||
|
||||
// Called for each captured frame.
|
||||
void FrameCaptured(const VideoFrame& frame, int64_t time_when_first_seen_ms);
|
||||
void FrameCaptured(const VideoFrame& frame, int64_t time_when_first_seen_us);
|
||||
|
||||
// Called for each sent frame.
|
||||
void FrameSent(uint32_t timestamp, int64_t time_sent_in_ms);
|
||||
void FrameSent(uint32_t timestamp, int64_t time_sent_in_us);
|
||||
|
||||
protected:
|
||||
void CheckForOveruse(); // Protected for test purposes.
|
||||
@ -92,15 +90,15 @@ class OveruseFrameDetector {
|
||||
class SendProcessingUsage;
|
||||
class CheckOveruseTask;
|
||||
struct FrameTiming {
|
||||
FrameTiming(int64_t capture_ntp_ms, uint32_t timestamp, int64_t now)
|
||||
: capture_ntp_ms(capture_ntp_ms),
|
||||
FrameTiming(int64_t capture_time_us, uint32_t timestamp, int64_t now)
|
||||
: capture_time_us(capture_time_us),
|
||||
timestamp(timestamp),
|
||||
capture_ms(now),
|
||||
last_send_ms(-1) {}
|
||||
int64_t capture_ntp_ms;
|
||||
capture_us(now),
|
||||
last_send_us(-1) {}
|
||||
int64_t capture_time_us;
|
||||
uint32_t timestamp;
|
||||
int64_t capture_ms;
|
||||
int64_t last_send_ms;
|
||||
int64_t capture_us;
|
||||
int64_t last_send_us;
|
||||
};
|
||||
|
||||
void EncodedFrameTimeMeasured(int encode_duration_ms);
|
||||
@ -125,12 +123,11 @@ class OveruseFrameDetector {
|
||||
// Stats metrics.
|
||||
CpuOveruseMetricsObserver* const metrics_observer_;
|
||||
rtc::Optional<CpuOveruseMetrics> metrics_ GUARDED_BY(task_checker_);
|
||||
Clock* const clock_;
|
||||
|
||||
int64_t num_process_times_ GUARDED_BY(task_checker_);
|
||||
|
||||
int64_t last_capture_time_ms_ GUARDED_BY(task_checker_);
|
||||
int64_t last_processed_capture_time_ms_ GUARDED_BY(task_checker_);
|
||||
int64_t last_capture_time_us_ GUARDED_BY(task_checker_);
|
||||
int64_t last_processed_capture_time_us_ GUARDED_BY(task_checker_);
|
||||
|
||||
// Number of pixels of last captured frame.
|
||||
int num_pixels_ GUARDED_BY(task_checker_);
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
|
||||
#include "webrtc/api/video/i420_buffer.h"
|
||||
#include "webrtc/base/event.h"
|
||||
#include "webrtc/system_wrappers/include/clock.h"
|
||||
#include "webrtc/base/fakeclock.h"
|
||||
#include "webrtc/test/gmock.h"
|
||||
#include "webrtc/test/gtest.h"
|
||||
#include "webrtc/video/overuse_frame_detector.h"
|
||||
@ -26,9 +26,8 @@ using ::testing::InvokeWithoutArgs;
|
||||
namespace {
|
||||
const int kWidth = 640;
|
||||
const int kHeight = 480;
|
||||
const int kFrameInterval33ms = 33;
|
||||
const int kProcessIntervalMs = 5000;
|
||||
const int kProcessTime5ms = 5;
|
||||
const int kFrameIntervalUs = 33 * rtc::kNumMicrosecsPerMillisec;
|
||||
const int kProcessTimeUs = 5 * rtc::kNumMicrosecsPerMillisec;
|
||||
} // namespace
|
||||
|
||||
class MockCpuOveruseObserver : public ScalingObserverInterface {
|
||||
@ -56,13 +55,11 @@ class CpuOveruseObserverImpl : public ScalingObserverInterface {
|
||||
|
||||
class OveruseFrameDetectorUnderTest : public OveruseFrameDetector {
|
||||
public:
|
||||
OveruseFrameDetectorUnderTest(Clock* clock,
|
||||
const CpuOveruseOptions& options,
|
||||
OveruseFrameDetectorUnderTest(const CpuOveruseOptions& options,
|
||||
ScalingObserverInterface* overuse_observer,
|
||||
EncodedFrameObserver* encoder_timing,
|
||||
CpuOveruseMetricsObserver* metrics_observer)
|
||||
: OveruseFrameDetector(clock,
|
||||
options,
|
||||
: OveruseFrameDetector(options,
|
||||
overuse_observer,
|
||||
encoder_timing,
|
||||
metrics_observer) {}
|
||||
@ -75,7 +72,6 @@ class OveruseFrameDetectorTest : public ::testing::Test,
|
||||
public CpuOveruseMetricsObserver {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
clock_.reset(new SimulatedClock(1234));
|
||||
observer_.reset(new MockCpuOveruseObserver());
|
||||
options_.min_process_count = 0;
|
||||
ReinitializeOveruseDetector();
|
||||
@ -83,7 +79,7 @@ class OveruseFrameDetectorTest : public ::testing::Test,
|
||||
|
||||
void ReinitializeOveruseDetector() {
|
||||
overuse_detector_.reset(new OveruseFrameDetectorUnderTest(
|
||||
clock_.get(), options_, observer_.get(), nullptr, this));
|
||||
options_, observer_.get(), nullptr, this));
|
||||
}
|
||||
|
||||
void OnEncodedFrameTimeMeasured(int encode_time_ms,
|
||||
@ -97,20 +93,20 @@ class OveruseFrameDetectorTest : public ::testing::Test,
|
||||
}
|
||||
|
||||
void InsertAndSendFramesWithInterval(int num_frames,
|
||||
int interval_ms,
|
||||
int interval_us,
|
||||
int width,
|
||||
int height,
|
||||
int delay_ms) {
|
||||
int delay_us) {
|
||||
VideoFrame frame(I420Buffer::Create(width, height),
|
||||
webrtc::kVideoRotation_0, 0);
|
||||
uint32_t timestamp = 0;
|
||||
while (num_frames-- > 0) {
|
||||
frame.set_timestamp(timestamp);
|
||||
overuse_detector_->FrameCaptured(frame, clock_->TimeInMilliseconds());
|
||||
clock_->AdvanceTimeMilliseconds(delay_ms);
|
||||
overuse_detector_->FrameSent(timestamp, clock_->TimeInMilliseconds());
|
||||
clock_->AdvanceTimeMilliseconds(interval_ms - delay_ms);
|
||||
timestamp += interval_ms * 90;
|
||||
overuse_detector_->FrameCaptured(frame, rtc::TimeMicros());
|
||||
clock_.AdvanceTimeMicros(delay_us);
|
||||
overuse_detector_->FrameSent(timestamp, rtc::TimeMicros());
|
||||
clock_.AdvanceTimeMicros(interval_us - delay_us);
|
||||
timestamp += interval_us * 90 / 1000;
|
||||
}
|
||||
}
|
||||
|
||||
@ -119,31 +115,32 @@ class OveruseFrameDetectorTest : public ::testing::Test,
|
||||
// the usage. From the tests where these are used, adding another sample
|
||||
// doesn't affect the expected outcome (this is mainly to check initial
|
||||
// values and whether the overuse detector has been reset or not).
|
||||
InsertAndSendFramesWithInterval(2, 1000, width, height, kFrameInterval33ms);
|
||||
InsertAndSendFramesWithInterval(2, rtc::kNumMicrosecsPerSec,
|
||||
width, height, kFrameIntervalUs);
|
||||
}
|
||||
void TriggerOveruse(int num_times) {
|
||||
const int kDelayMs = 32;
|
||||
const int kDelayUs = 32 * rtc::kNumMicrosecsPerMillisec;
|
||||
for (int i = 0; i < num_times; ++i) {
|
||||
InsertAndSendFramesWithInterval(
|
||||
1000, kFrameInterval33ms, kWidth, kHeight, kDelayMs);
|
||||
1000, kFrameIntervalUs, kWidth, kHeight, kDelayUs);
|
||||
overuse_detector_->CheckForOveruse();
|
||||
}
|
||||
}
|
||||
|
||||
void TriggerUnderuse() {
|
||||
const int kDelayMs1 = 5;
|
||||
const int kDelayMs2 = 6;
|
||||
const int kDelayUs1 = 5000;
|
||||
const int kDelayUs2 = 6000;
|
||||
InsertAndSendFramesWithInterval(
|
||||
1300, kFrameInterval33ms, kWidth, kHeight, kDelayMs1);
|
||||
1300, kFrameIntervalUs, kWidth, kHeight, kDelayUs1);
|
||||
InsertAndSendFramesWithInterval(
|
||||
1, kFrameInterval33ms, kWidth, kHeight, kDelayMs2);
|
||||
1, kFrameIntervalUs, kWidth, kHeight, kDelayUs2);
|
||||
overuse_detector_->CheckForOveruse();
|
||||
}
|
||||
|
||||
int UsagePercent() { return metrics_.encode_usage_percent; }
|
||||
|
||||
CpuOveruseOptions options_;
|
||||
std::unique_ptr<SimulatedClock> clock_;
|
||||
rtc::ScopedFakeClock clock_;
|
||||
std::unique_ptr<MockCpuOveruseObserver> observer_;
|
||||
std::unique_ptr<OveruseFrameDetectorUnderTest> overuse_detector_;
|
||||
CpuOveruseMetrics metrics_;
|
||||
@ -171,7 +168,7 @@ TEST_F(OveruseFrameDetectorTest, OveruseAndRecover) {
|
||||
|
||||
TEST_F(OveruseFrameDetectorTest, OveruseAndRecoverWithNoObserver) {
|
||||
overuse_detector_.reset(new OveruseFrameDetectorUnderTest(
|
||||
clock_.get(), options_, nullptr, nullptr, this));
|
||||
options_, nullptr, nullptr, this));
|
||||
EXPECT_CALL(*(observer_.get()), ScaleDown(reason_)).Times(0);
|
||||
TriggerOveruse(options_.high_threshold_consecutive_count);
|
||||
EXPECT_CALL(*(observer_.get()), ScaleUp(reason_)).Times(0);
|
||||
@ -187,15 +184,16 @@ TEST_F(OveruseFrameDetectorTest, DoubleOveruseAndRecover) {
|
||||
}
|
||||
|
||||
TEST_F(OveruseFrameDetectorTest, TriggerUnderuseWithMinProcessCount) {
|
||||
const int kProcessIntervalUs = 5 * rtc::kNumMicrosecsPerSec;
|
||||
options_.min_process_count = 1;
|
||||
CpuOveruseObserverImpl overuse_observer;
|
||||
overuse_detector_.reset(new OveruseFrameDetectorUnderTest(
|
||||
clock_.get(), options_, &overuse_observer, nullptr, this));
|
||||
options_, &overuse_observer, nullptr, this));
|
||||
InsertAndSendFramesWithInterval(
|
||||
1200, kFrameInterval33ms, kWidth, kHeight, kProcessTime5ms);
|
||||
1200, kFrameIntervalUs, kWidth, kHeight, kProcessTimeUs);
|
||||
overuse_detector_->CheckForOveruse();
|
||||
EXPECT_EQ(0, overuse_observer.normaluse_);
|
||||
clock_->AdvanceTimeMilliseconds(kProcessIntervalMs);
|
||||
clock_.AdvanceTimeMicros(kProcessIntervalUs);
|
||||
overuse_detector_->CheckForOveruse();
|
||||
EXPECT_EQ(1, overuse_observer.normaluse_);
|
||||
}
|
||||
@ -224,15 +222,15 @@ TEST_F(OveruseFrameDetectorTest, IncorrectConsecutiveCountTriggersNoOveruse) {
|
||||
|
||||
TEST_F(OveruseFrameDetectorTest, ProcessingUsage) {
|
||||
InsertAndSendFramesWithInterval(
|
||||
1000, kFrameInterval33ms, kWidth, kHeight, kProcessTime5ms);
|
||||
EXPECT_EQ(kProcessTime5ms * 100 / kFrameInterval33ms, UsagePercent());
|
||||
1000, kFrameIntervalUs, kWidth, kHeight, kProcessTimeUs);
|
||||
EXPECT_EQ(kProcessTimeUs * 100 / kFrameIntervalUs, UsagePercent());
|
||||
}
|
||||
|
||||
TEST_F(OveruseFrameDetectorTest, ResetAfterResolutionChange) {
|
||||
ForceUpdate(kWidth, kHeight);
|
||||
EXPECT_EQ(InitialUsage(), UsagePercent());
|
||||
InsertAndSendFramesWithInterval(
|
||||
1000, kFrameInterval33ms, kWidth, kHeight, kProcessTime5ms);
|
||||
1000, kFrameIntervalUs, kWidth, kHeight, kProcessTimeUs);
|
||||
EXPECT_NE(InitialUsage(), UsagePercent());
|
||||
// Verify reset (with new width/height).
|
||||
ForceUpdate(kWidth, kHeight + 1);
|
||||
@ -243,15 +241,16 @@ TEST_F(OveruseFrameDetectorTest, ResetAfterFrameTimeout) {
|
||||
ForceUpdate(kWidth, kHeight);
|
||||
EXPECT_EQ(InitialUsage(), UsagePercent());
|
||||
InsertAndSendFramesWithInterval(
|
||||
1000, kFrameInterval33ms, kWidth, kHeight, kProcessTime5ms);
|
||||
1000, kFrameIntervalUs, kWidth, kHeight, kProcessTimeUs);
|
||||
EXPECT_NE(InitialUsage(), UsagePercent());
|
||||
InsertAndSendFramesWithInterval(
|
||||
2, options_.frame_timeout_interval_ms, kWidth, kHeight, kProcessTime5ms);
|
||||
2, options_.frame_timeout_interval_ms *
|
||||
rtc::kNumMicrosecsPerMillisec, kWidth, kHeight, kProcessTimeUs);
|
||||
EXPECT_NE(InitialUsage(), UsagePercent());
|
||||
// Verify reset.
|
||||
InsertAndSendFramesWithInterval(
|
||||
2, options_.frame_timeout_interval_ms + 1, kWidth, kHeight,
|
||||
kProcessTime5ms);
|
||||
2, (options_.frame_timeout_interval_ms + 1) *
|
||||
rtc::kNumMicrosecsPerMillisec, kWidth, kHeight, kProcessTimeUs);
|
||||
ForceUpdate(kWidth, kHeight);
|
||||
EXPECT_EQ(InitialUsage(), UsagePercent());
|
||||
}
|
||||
@ -260,19 +259,19 @@ TEST_F(OveruseFrameDetectorTest, MinFrameSamplesBeforeUpdating) {
|
||||
options_.min_frame_samples = 40;
|
||||
ReinitializeOveruseDetector();
|
||||
InsertAndSendFramesWithInterval(
|
||||
40, kFrameInterval33ms, kWidth, kHeight, kProcessTime5ms);
|
||||
40, kFrameIntervalUs, kWidth, kHeight, kProcessTimeUs);
|
||||
EXPECT_EQ(InitialUsage(), UsagePercent());
|
||||
// Pass time far enough to digest all previous samples.
|
||||
clock_->AdvanceTimeMilliseconds(1000);
|
||||
InsertAndSendFramesWithInterval(1, kFrameInterval33ms, kWidth, kHeight,
|
||||
kProcessTime5ms);
|
||||
clock_.AdvanceTimeMicros(rtc::kNumMicrosecsPerSec);
|
||||
InsertAndSendFramesWithInterval(1, kFrameIntervalUs, kWidth, kHeight,
|
||||
kProcessTimeUs);
|
||||
// The last sample has not been processed here.
|
||||
EXPECT_EQ(InitialUsage(), UsagePercent());
|
||||
|
||||
// Pass time far enough to digest all previous samples, 41 in total.
|
||||
clock_->AdvanceTimeMilliseconds(1000);
|
||||
clock_.AdvanceTimeMicros(rtc::kNumMicrosecsPerSec);
|
||||
InsertAndSendFramesWithInterval(
|
||||
1, kFrameInterval33ms, kWidth, kHeight, kProcessTime5ms);
|
||||
1, kFrameIntervalUs, kWidth, kHeight, kProcessTimeUs);
|
||||
EXPECT_NE(InitialUsage(), UsagePercent());
|
||||
}
|
||||
|
||||
@ -284,19 +283,19 @@ TEST_F(OveruseFrameDetectorTest, InitialProcessingUsage) {
|
||||
TEST_F(OveruseFrameDetectorTest, MeasuresMultipleConcurrentSamples) {
|
||||
EXPECT_CALL(*(observer_.get()), ScaleDown(reason_))
|
||||
.Times(testing::AtLeast(1));
|
||||
static const int kIntervalMs = 33;
|
||||
static const int kIntervalUs = 33 * rtc::kNumMicrosecsPerMillisec;
|
||||
static const size_t kNumFramesEncodingDelay = 3;
|
||||
VideoFrame frame(I420Buffer::Create(kWidth, kHeight),
|
||||
webrtc::kVideoRotation_0, 0);
|
||||
for (size_t i = 0; i < 1000; ++i) {
|
||||
// Unique timestamps.
|
||||
frame.set_timestamp(static_cast<uint32_t>(i));
|
||||
overuse_detector_->FrameCaptured(frame, clock_->TimeInMilliseconds());
|
||||
clock_->AdvanceTimeMilliseconds(kIntervalMs);
|
||||
overuse_detector_->FrameCaptured(frame, rtc::TimeMicros());
|
||||
clock_.AdvanceTimeMicros(kIntervalUs);
|
||||
if (i > kNumFramesEncodingDelay) {
|
||||
overuse_detector_->FrameSent(
|
||||
static_cast<uint32_t>(i - kNumFramesEncodingDelay),
|
||||
clock_->TimeInMilliseconds());
|
||||
rtc::TimeMicros());
|
||||
}
|
||||
overuse_detector_->CheckForOveruse();
|
||||
}
|
||||
@ -306,22 +305,22 @@ TEST_F(OveruseFrameDetectorTest, UpdatesExistingSamples) {
|
||||
// >85% encoding time should trigger overuse.
|
||||
EXPECT_CALL(*(observer_.get()), ScaleDown(reason_))
|
||||
.Times(testing::AtLeast(1));
|
||||
static const int kIntervalMs = 33;
|
||||
static const int kDelayMs = 30;
|
||||
static const int kIntervalUs = 33 * rtc::kNumMicrosecsPerMillisec;
|
||||
static const int kDelayUs = 30 * rtc::kNumMicrosecsPerMillisec;
|
||||
VideoFrame frame(I420Buffer::Create(kWidth, kHeight),
|
||||
webrtc::kVideoRotation_0, 0);
|
||||
uint32_t timestamp = 0;
|
||||
for (size_t i = 0; i < 1000; ++i) {
|
||||
frame.set_timestamp(timestamp);
|
||||
overuse_detector_->FrameCaptured(frame, clock_->TimeInMilliseconds());
|
||||
overuse_detector_->FrameCaptured(frame, rtc::TimeMicros());
|
||||
// Encode and send first parts almost instantly.
|
||||
clock_->AdvanceTimeMilliseconds(1);
|
||||
overuse_detector_->FrameSent(timestamp, clock_->TimeInMilliseconds());
|
||||
clock_.AdvanceTimeMicros(rtc::kNumMicrosecsPerMillisec);
|
||||
overuse_detector_->FrameSent(timestamp, rtc::TimeMicros());
|
||||
// Encode heavier part, resulting in >85% usage total.
|
||||
clock_->AdvanceTimeMilliseconds(kDelayMs - 1);
|
||||
overuse_detector_->FrameSent(timestamp, clock_->TimeInMilliseconds());
|
||||
clock_->AdvanceTimeMilliseconds(kIntervalMs - kDelayMs);
|
||||
timestamp += kIntervalMs * 90;
|
||||
clock_.AdvanceTimeMicros(kDelayUs - rtc::kNumMicrosecsPerMillisec);
|
||||
overuse_detector_->FrameSent(timestamp, rtc::TimeMicros());
|
||||
clock_.AdvanceTimeMicros(kIntervalUs - kDelayUs);
|
||||
timestamp += kIntervalUs * 90 / 1000;
|
||||
overuse_detector_->CheckForOveruse();
|
||||
}
|
||||
}
|
||||
@ -345,12 +344,12 @@ TEST_F(OveruseFrameDetectorTest, RunOnTqNormalUsage) {
|
||||
}));
|
||||
|
||||
queue.PostTask([this, &event] {
|
||||
const int kDelayMs1 = 5;
|
||||
const int kDelayMs2 = 6;
|
||||
InsertAndSendFramesWithInterval(1300, kFrameInterval33ms, kWidth, kHeight,
|
||||
kDelayMs1);
|
||||
InsertAndSendFramesWithInterval(1, kFrameInterval33ms, kWidth, kHeight,
|
||||
kDelayMs2);
|
||||
const int kDelayUs1 = 5 * rtc::kNumMicrosecsPerMillisec;
|
||||
const int kDelayUs2 = 6 * rtc::kNumMicrosecsPerMillisec;
|
||||
InsertAndSendFramesWithInterval(1300, kFrameIntervalUs, kWidth, kHeight,
|
||||
kDelayUs1);
|
||||
InsertAndSendFramesWithInterval(1, kFrameIntervalUs, kWidth, kHeight,
|
||||
kDelayUs2);
|
||||
});
|
||||
|
||||
EXPECT_TRUE(event.Wait(10000));
|
||||
|
||||
@ -85,11 +85,11 @@ class ViEEncoder::EncodeTask : public rtc::QueuedTask {
|
||||
public:
|
||||
EncodeTask(const VideoFrame& frame,
|
||||
ViEEncoder* vie_encoder,
|
||||
int64_t time_when_posted_in_ms,
|
||||
int64_t time_when_posted_us,
|
||||
bool log_stats)
|
||||
: frame_(frame),
|
||||
vie_encoder_(vie_encoder),
|
||||
time_when_posted_ms_(time_when_posted_in_ms),
|
||||
time_when_posted_us_(time_when_posted_us),
|
||||
log_stats_(log_stats) {
|
||||
++vie_encoder_->posted_frames_waiting_for_encode_;
|
||||
}
|
||||
@ -102,7 +102,7 @@ class ViEEncoder::EncodeTask : public rtc::QueuedTask {
|
||||
frame_.height());
|
||||
++vie_encoder_->captured_frame_count_;
|
||||
if (--vie_encoder_->posted_frames_waiting_for_encode_ == 0) {
|
||||
vie_encoder_->EncodeVideoFrame(frame_, time_when_posted_ms_);
|
||||
vie_encoder_->EncodeVideoFrame(frame_, time_when_posted_us_);
|
||||
} else {
|
||||
// There is a newer frame in flight. Do not encode this frame.
|
||||
LOG(LS_VERBOSE)
|
||||
@ -122,7 +122,7 @@ class ViEEncoder::EncodeTask : public rtc::QueuedTask {
|
||||
}
|
||||
VideoFrame frame_;
|
||||
ViEEncoder* const vie_encoder_;
|
||||
const int64_t time_when_posted_ms_;
|
||||
const int64_t time_when_posted_us_;
|
||||
const bool log_stats_;
|
||||
};
|
||||
|
||||
@ -250,8 +250,7 @@ ViEEncoder::ViEEncoder(uint32_t number_of_cores,
|
||||
codec_type_(PayloadNameToCodecType(settings.payload_name)
|
||||
.value_or(VideoCodecType::kVideoCodecUnknown)),
|
||||
video_sender_(Clock::GetRealTimeClock(), this, this),
|
||||
overuse_detector_(Clock::GetRealTimeClock(),
|
||||
GetCpuOveruseOptions(settings.full_overuse_time),
|
||||
overuse_detector_(GetCpuOveruseOptions(settings.full_overuse_time),
|
||||
this,
|
||||
encoder_timing,
|
||||
stats_proxy),
|
||||
@ -493,7 +492,7 @@ void ViEEncoder::OnFrame(const VideoFrame& video_frame) {
|
||||
|
||||
last_captured_timestamp_ = incoming_frame.ntp_time_ms();
|
||||
encoder_queue_.PostTask(std::unique_ptr<rtc::QueuedTask>(new EncodeTask(
|
||||
incoming_frame, this, clock_->TimeInMilliseconds(), log_stats)));
|
||||
incoming_frame, this, rtc::TimeMicros(), log_stats)));
|
||||
}
|
||||
|
||||
bool ViEEncoder::EncoderPaused() const {
|
||||
@ -525,7 +524,7 @@ void ViEEncoder::TraceFrameDropEnd() {
|
||||
}
|
||||
|
||||
void ViEEncoder::EncodeVideoFrame(const VideoFrame& video_frame,
|
||||
int64_t time_when_posted_in_ms) {
|
||||
int64_t time_when_posted_us) {
|
||||
RTC_DCHECK_RUN_ON(&encoder_queue_);
|
||||
|
||||
if (pre_encode_callback_)
|
||||
@ -565,7 +564,7 @@ void ViEEncoder::EncodeVideoFrame(const VideoFrame& video_frame,
|
||||
TRACE_EVENT_ASYNC_STEP0("webrtc", "Video", video_frame.render_time_ms(),
|
||||
"Encode");
|
||||
|
||||
overuse_detector_.FrameCaptured(video_frame, time_when_posted_in_ms);
|
||||
overuse_detector_.FrameCaptured(video_frame, time_when_posted_us);
|
||||
|
||||
if (codec_type_ == webrtc::kVideoCodecVP8) {
|
||||
webrtc::CodecSpecificInfo codec_specific_info;
|
||||
@ -606,12 +605,12 @@ EncodedImageCallback::Result ViEEncoder::OnEncodedImage(
|
||||
EncodedImageCallback::Result result =
|
||||
sink_->OnEncodedImage(encoded_image, codec_specific_info, fragmentation);
|
||||
|
||||
int64_t time_sent = clock_->TimeInMilliseconds();
|
||||
int64_t time_sent_us = rtc::TimeMicros();
|
||||
uint32_t timestamp = encoded_image._timeStamp;
|
||||
const int qp = encoded_image.qp_;
|
||||
encoder_queue_.PostTask([this, timestamp, time_sent, qp] {
|
||||
encoder_queue_.PostTask([this, timestamp, time_sent_us, qp] {
|
||||
RTC_DCHECK_RUN_ON(&encoder_queue_);
|
||||
overuse_detector_.FrameSent(timestamp, time_sent);
|
||||
overuse_detector_.FrameSent(timestamp, time_sent_us);
|
||||
if (quality_scaler_)
|
||||
quality_scaler_->ReportQP(qp);
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user