Include duration of pauses into sum of squared frames duration.

Bug: webrtc:10502
Change-Id: Ie905c0c9e8ca8fe07be585ce5a0d75e9eed6e865
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/130499
Commit-Queue: Sergey Silkin <ssilkin@webrtc.org>
Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#27435}
This commit is contained in:
Sergey Silkin 2019-04-03 10:57:26 +02:00 committed by Commit Bot
parent 78a5e96001
commit fc6f3e5873
2 changed files with 51 additions and 33 deletions

View File

@ -1263,30 +1263,41 @@ TEST_P(ReceiveStatisticsProxyTestWithContent, FreezesAreReported) {
}
TEST_P(ReceiveStatisticsProxyTestWithContent, HarmonicFrameRateIsReported) {
const int kInterFrameDelayMs = 33;
const int kFreezeDelayMs = 200;
const int kCallDurationMs =
kMinRequiredSamples * kInterFrameDelayMs + kFreezeDelayMs;
const int kFrameDurationMs = 33;
const int kFreezeDurationMs = 200;
const int kPauseDurationMs = 10000;
const int kCallDurationMs = kMinRequiredSamples * kFrameDurationMs +
kFreezeDurationMs + kPauseDurationMs;
webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
for (int i = 0; i < kMinRequiredSamples; ++i) {
fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
fake_clock_.AdvanceTimeMilliseconds(kFrameDurationMs);
statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
statistics_proxy_->OnRenderedFrame(frame);
}
// Add extra freeze.
fake_clock_.AdvanceTimeMilliseconds(kFreezeDelayMs);
// Freezes and pauses should be included into harmonic frame rate.
// Add freeze.
fake_clock_.AdvanceTimeMilliseconds(kFreezeDurationMs);
statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
statistics_proxy_->OnRenderedFrame(frame);
// Add pause.
fake_clock_.AdvanceTimeMilliseconds(kPauseDurationMs);
statistics_proxy_->OnStreamInactive();
statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
statistics_proxy_->OnRenderedFrame(frame);
statistics_proxy_.reset();
double kSumSquaredInterframeDelaysSecs =
double kSumSquaredFrameDurationSecs =
(kMinRequiredSamples - 1) *
(kInterFrameDelayMs / 1000.0 * kInterFrameDelayMs / 1000.0);
kSumSquaredInterframeDelaysSecs +=
kFreezeDelayMs / 1000.0 * kFreezeDelayMs / 1000.0;
(kFrameDurationMs / 1000.0 * kFrameDurationMs / 1000.0);
kSumSquaredFrameDurationSecs +=
kFreezeDurationMs / 1000.0 * kFreezeDurationMs / 1000.0;
kSumSquaredFrameDurationSecs +=
kPauseDurationMs / 1000.0 * kPauseDurationMs / 1000.0;
const int kExpectedHarmonicFrameRateFps =
std::round(kCallDurationMs / (1000 * kSumSquaredInterframeDelaysSecs));
std::round(kCallDurationMs / (1000 * kSumSquaredFrameDurationSecs));
if (videocontenttypehelpers::IsScreenshare(content_type_)) {
EXPECT_EQ(kExpectedHarmonicFrameRateFps,
metrics::MinSample("WebRTC.Video.Screenshare.HarmonicFrameRate"));

View File

@ -146,35 +146,42 @@ void VideoQualityObserver::OnRenderedFrame(const VideoFrame& frame,
auto blocky_frame_it = blocky_frames_.find(frame.timestamp());
if (!is_paused_ && num_frames_rendered_ > 0) {
if (num_frames_rendered_ > 0) {
// Process inter-frame delay.
const int64_t interframe_delay_ms = now_ms - last_frame_rendered_ms_;
const double interframe_delays_secs = interframe_delay_ms / 1000.0;
// Sum of squared inter frame intervals is used to calculate the harmonic
// frame rate metric. The metric aims to reflect overall experience related
// to smoothness of video playback and includes both freezes and pauses.
sum_squared_interframe_delays_secs_ +=
interframe_delays_secs * interframe_delays_secs;
render_interframe_delays_.AddSample(interframe_delay_ms);
bool was_freeze = false;
if (render_interframe_delays_.Size() >= kMinFrameSamplesToDetectFreeze) {
const absl::optional<int64_t> avg_interframe_delay =
render_interframe_delays_.GetAverageRoundedDown();
RTC_DCHECK(avg_interframe_delay);
was_freeze = interframe_delay_ms >=
std::max(3 * *avg_interframe_delay,
*avg_interframe_delay + kMinIncreaseForFreezeMs);
}
if (!is_paused_) {
render_interframe_delays_.AddSample(interframe_delay_ms);
if (was_freeze) {
freezes_durations_.Add(interframe_delay_ms);
smooth_playback_durations_.Add(last_frame_rendered_ms_ -
last_unfreeze_time_ms_);
last_unfreeze_time_ms_ = now_ms;
} else {
// Count spatial metrics if there were no freeze.
time_in_resolution_ms_[current_resolution_] += interframe_delay_ms;
bool was_freeze = false;
if (render_interframe_delays_.Size() >= kMinFrameSamplesToDetectFreeze) {
const absl::optional<int64_t> avg_interframe_delay =
render_interframe_delays_.GetAverageRoundedDown();
RTC_DCHECK(avg_interframe_delay);
was_freeze = interframe_delay_ms >=
std::max(3 * *avg_interframe_delay,
*avg_interframe_delay + kMinIncreaseForFreezeMs);
}
if (is_last_frame_blocky_) {
time_in_blocky_video_ms_ += interframe_delay_ms;
if (was_freeze) {
freezes_durations_.Add(interframe_delay_ms);
smooth_playback_durations_.Add(last_frame_rendered_ms_ -
last_unfreeze_time_ms_);
last_unfreeze_time_ms_ = now_ms;
} else {
// Count spatial metrics if there were no freeze.
time_in_resolution_ms_[current_resolution_] += interframe_delay_ms;
if (is_last_frame_blocky_) {
time_in_blocky_video_ms_ += interframe_delay_ms;
}
}
}
}