Move stats for decoded frames per second from VCMTiming to ReceiveStatisticsProxy.

Bug: none
Change-Id: I631a2b1cb550dded6d1e1daf47ac35583298d30d
Reviewed-on: https://webrtc-review.googlesource.com/36121
Commit-Queue: Åsa Persson <asapersson@webrtc.org>
Reviewed-by: Rasmus Brandt <brandtr@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#21757}
This commit is contained in:
Åsa Persson
2018-01-24 17:04:07 +01:00
committed by Commit Bot
parent 91af24a74b
commit b9b07eaf28
4 changed files with 62 additions and 3 deletions

View File

@ -50,6 +50,7 @@ VCMTiming::~VCMTiming() {
}
}
// TODO(asapersson): Move stats to ReceiveStatisticsProxy.
void VCMTiming::UpdateHistograms() const {
rtc::CritScope cs(&crit_sect_);
if (num_decoded_frames_ == 0) {
@ -60,9 +61,6 @@ void VCMTiming::UpdateHistograms() const {
if (elapsed_sec < metrics::kMinRunTimeInSeconds) {
return;
}
RTC_HISTOGRAM_COUNTS_100(
"WebRTC.Video.DecodedFramesPerSecond",
static_cast<int>((num_decoded_frames_ / elapsed_sec) + 0.5f));
RTC_HISTOGRAM_PERCENTAGE(
"WebRTC.Video.DelayedFramesToRenderer",
num_delayed_decoded_frames_ * 100 / num_decoded_frames_);

View File

@ -18,6 +18,7 @@
#include "modules/video_coding/include/video_codec_interface.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "rtc_base/timeutils.h"
#include "system_wrappers/include/clock.h"
#include "system_wrappers/include/metrics.h"
@ -146,6 +147,18 @@ void ReceiveStatisticsProxy::UpdateHistograms() {
}
}
if (first_decoded_frame_time_ms_) {
const int64_t elapsed_ms =
(clock_->TimeInMilliseconds() - *first_decoded_frame_time_ms_);
if (elapsed_ms >=
metrics::kMinRunTimeInSeconds * rtc::kNumMillisecsPerSec) {
RTC_HISTOGRAM_COUNTS_100(
"WebRTC.Video.DecodedFramesPerSecond",
static_cast<int>((stats_.frames_decoded * 1000.0f / elapsed_ms) +
0.5f));
}
}
const int kMinRequiredSamples = 200;
int samples = static_cast<int>(render_fps_tracker_.TotalSampleCount());
if (samples >= kMinRequiredSamples) {
@ -664,6 +677,8 @@ void ReceiveStatisticsProxy::OnDecodedFrame(rtc::Optional<uint8_t> qp,
interframe_delay_ms);
content_specific_stats->flow_duration_ms += interframe_delay_ms;
}
if (stats_.frames_decoded == 1)
first_decoded_frame_time_ms_.emplace(now);
last_decoded_frame_time_ms_.emplace(now);
}

View File

@ -182,6 +182,7 @@ class ReceiveStatisticsProxy : public VCMReceiveStatisticsCallback,
int64_t avg_rtt_ms_ RTC_GUARDED_BY(crit_);
mutable std::map<int64_t, size_t> frame_window_ RTC_GUARDED_BY(&crit_);
VideoContentType last_content_type_ RTC_GUARDED_BY(&crit_);
rtc::Optional<int64_t> first_decoded_frame_time_ms_ RTC_GUARDED_BY(&crit_);
rtc::Optional<int64_t> last_decoded_frame_time_ms_ RTC_GUARDED_BY(&crit_);
// Mutable because calling Max() on MovingMaxCounter is not const. Yet it is
// called from const GetStats().

View File

@ -76,6 +76,51 @@ TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameIncreasesFramesDecoded) {
}
}
TEST_F(ReceiveStatisticsProxyTest, DecodedFpsIsReported) {
const int kFps = 20;
const int kRequiredSamples = metrics::kMinRunTimeInSeconds * kFps;
for (int i = 0; i < kRequiredSamples; ++i) {
statistics_proxy_->OnDecodedFrame(rtc::Optional<uint8_t>(),
VideoContentType::UNSPECIFIED);
fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
}
statistics_proxy_.reset();
EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DecodedFramesPerSecond", kFps));
}
TEST_F(ReceiveStatisticsProxyTest, DecodedFpsIsNotReportedForTooFewSamples) {
const int kFps = 20;
const int kRequiredSamples = metrics::kMinRunTimeInSeconds * kFps;
for (int i = 0; i < kRequiredSamples - 1; ++i) {
statistics_proxy_->OnDecodedFrame(rtc::Optional<uint8_t>(),
VideoContentType::UNSPECIFIED);
fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
}
statistics_proxy_.reset();
EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
}
TEST_F(ReceiveStatisticsProxyTest, DecodedFpsIsReportedWithQpReset) {
const int kFps1 = 10;
for (int i = 0; i < metrics::kMinRunTimeInSeconds * kFps1; ++i) {
statistics_proxy_->OnDecodedFrame(rtc::Optional<uint8_t>(),
VideoContentType::UNSPECIFIED);
fake_clock_.AdvanceTimeMilliseconds(1000 / kFps1);
}
// First QP value received, resets frames decoded.
const int kFps2 = 20;
for (int i = 0; i < metrics::kMinRunTimeInSeconds * kFps2; ++i) {
statistics_proxy_->OnDecodedFrame(rtc::Optional<uint8_t>(1u),
VideoContentType::UNSPECIFIED);
fake_clock_.AdvanceTimeMilliseconds(1000 / kFps2);
}
statistics_proxy_.reset();
EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
EXPECT_EQ(1,
metrics::NumEvents("WebRTC.Video.DecodedFramesPerSecond", kFps2));
}
TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameWithQpResetsFramesDecoded) {
EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_decoded);
for (uint32_t i = 1; i <= 3; ++i) {