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:
@ -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_);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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().
|
||||
|
||||
@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user