Move stats for delayed frames to renderer from VCMTiming to ReceiveStatisticsProxy.
Bug: none Change-Id: If62cc40cf00bc4d657a31a89640d03812cff388e Reviewed-on: https://webrtc-review.googlesource.com/74500 Commit-Queue: Åsa Persson <asapersson@webrtc.org> Reviewed-by: Rasmus Brandt <brandtr@webrtc.org> Cr-Commit-Position: refs/heads/master@{#23526}
This commit is contained in:
@ -14,7 +14,6 @@
|
|||||||
|
|
||||||
#include "rtc_base/time/timestamp_extrapolator.h"
|
#include "rtc_base/time/timestamp_extrapolator.h"
|
||||||
#include "system_wrappers/include/clock.h"
|
#include "system_wrappers/include/clock.h"
|
||||||
#include "system_wrappers/include/metrics.h"
|
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
@ -31,10 +30,7 @@ VCMTiming::VCMTiming(Clock* clock, VCMTiming* master_timing)
|
|||||||
last_decode_ms_(0),
|
last_decode_ms_(0),
|
||||||
prev_frame_timestamp_(0),
|
prev_frame_timestamp_(0),
|
||||||
timing_frame_info_(),
|
timing_frame_info_(),
|
||||||
num_decoded_frames_(0),
|
num_decoded_frames_(0) {
|
||||||
num_delayed_decoded_frames_(0),
|
|
||||||
first_decoded_frame_ms_(-1),
|
|
||||||
sum_missed_render_deadline_ms_(0) {
|
|
||||||
if (master_timing == NULL) {
|
if (master_timing == NULL) {
|
||||||
master_ = true;
|
master_ = true;
|
||||||
ts_extrapolator_ = new TimestampExtrapolator(clock_->TimeInMilliseconds());
|
ts_extrapolator_ = new TimestampExtrapolator(clock_->TimeInMilliseconds());
|
||||||
@ -44,33 +40,11 @@ VCMTiming::VCMTiming(Clock* clock, VCMTiming* master_timing)
|
|||||||
}
|
}
|
||||||
|
|
||||||
VCMTiming::~VCMTiming() {
|
VCMTiming::~VCMTiming() {
|
||||||
UpdateHistograms();
|
|
||||||
if (master_) {
|
if (master_) {
|
||||||
delete ts_extrapolator_;
|
delete ts_extrapolator_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(asapersson): Move stats to ReceiveStatisticsProxy.
|
|
||||||
void VCMTiming::UpdateHistograms() const {
|
|
||||||
rtc::CritScope cs(&crit_sect_);
|
|
||||||
if (num_decoded_frames_ == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
int64_t elapsed_sec =
|
|
||||||
(clock_->TimeInMilliseconds() - first_decoded_frame_ms_) / 1000;
|
|
||||||
if (elapsed_sec < metrics::kMinRunTimeInSeconds) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
RTC_HISTOGRAM_PERCENTAGE(
|
|
||||||
"WebRTC.Video.DelayedFramesToRenderer",
|
|
||||||
num_delayed_decoded_frames_ * 100 / num_decoded_frames_);
|
|
||||||
if (num_delayed_decoded_frames_ > 0) {
|
|
||||||
RTC_HISTOGRAM_COUNTS_1000(
|
|
||||||
"WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs",
|
|
||||||
sum_missed_render_deadline_ms_ / num_delayed_decoded_frames_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void VCMTiming::Reset() {
|
void VCMTiming::Reset() {
|
||||||
rtc::CritScope cs(&crit_sect_);
|
rtc::CritScope cs(&crit_sect_);
|
||||||
ts_extrapolator_->Reset(clock_->TimeInMilliseconds());
|
ts_extrapolator_->Reset(clock_->TimeInMilliseconds());
|
||||||
@ -183,17 +157,7 @@ void VCMTiming::StopDecodeTimer(uint32_t time_stamp,
|
|||||||
codec_timer_->AddTiming(decode_time_ms, now_ms);
|
codec_timer_->AddTiming(decode_time_ms, now_ms);
|
||||||
assert(decode_time_ms >= 0);
|
assert(decode_time_ms >= 0);
|
||||||
last_decode_ms_ = decode_time_ms;
|
last_decode_ms_ = decode_time_ms;
|
||||||
|
|
||||||
// Update stats.
|
|
||||||
++num_decoded_frames_;
|
++num_decoded_frames_;
|
||||||
if (num_decoded_frames_ == 1) {
|
|
||||||
first_decoded_frame_ms_ = now_ms;
|
|
||||||
}
|
|
||||||
int time_until_rendering_ms = render_time_ms - render_delay_ms_ - now_ms;
|
|
||||||
if (time_until_rendering_ms < 0) {
|
|
||||||
sum_missed_render_deadline_ms_ += -time_until_rendering_ms;
|
|
||||||
++num_delayed_decoded_frames_;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VCMTiming::IncomingTimestamp(uint32_t time_stamp, int64_t now_ms) {
|
void VCMTiming::IncomingTimestamp(uint32_t time_stamp, int64_t now_ms) {
|
||||||
|
@ -107,8 +107,6 @@ class VCMTiming {
|
|||||||
int TargetDelayInternal() const RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
|
int TargetDelayInternal() const RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void UpdateHistograms() const;
|
|
||||||
|
|
||||||
rtc::CriticalSection crit_sect_;
|
rtc::CriticalSection crit_sect_;
|
||||||
Clock* const clock_;
|
Clock* const clock_;
|
||||||
bool master_ RTC_GUARDED_BY(crit_sect_);
|
bool master_ RTC_GUARDED_BY(crit_sect_);
|
||||||
@ -127,12 +125,7 @@ class VCMTiming {
|
|||||||
int last_decode_ms_ RTC_GUARDED_BY(crit_sect_);
|
int last_decode_ms_ RTC_GUARDED_BY(crit_sect_);
|
||||||
uint32_t prev_frame_timestamp_ RTC_GUARDED_BY(crit_sect_);
|
uint32_t prev_frame_timestamp_ RTC_GUARDED_BY(crit_sect_);
|
||||||
rtc::Optional<TimingFrameInfo> timing_frame_info_ RTC_GUARDED_BY(crit_sect_);
|
rtc::Optional<TimingFrameInfo> timing_frame_info_ RTC_GUARDED_BY(crit_sect_);
|
||||||
|
|
||||||
// Statistics.
|
|
||||||
size_t num_decoded_frames_ RTC_GUARDED_BY(crit_sect_);
|
size_t num_decoded_frames_ RTC_GUARDED_BY(crit_sect_);
|
||||||
size_t num_delayed_decoded_frames_ RTC_GUARDED_BY(crit_sect_);
|
|
||||||
int64_t first_decoded_frame_ms_ RTC_GUARDED_BY(crit_sect_);
|
|
||||||
uint64_t sum_missed_render_deadline_ms_ RTC_GUARDED_BY(crit_sect_);
|
|
||||||
};
|
};
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|
||||||
|
@ -60,10 +60,9 @@ void HistogramTest::VerifyHistogramStats(bool use_rtx,
|
|||||||
|
|
||||||
bool MinMetricRunTimePassed() {
|
bool MinMetricRunTimePassed() {
|
||||||
int64_t now_ms = Clock::GetRealTimeClock()->TimeInMilliseconds();
|
int64_t now_ms = Clock::GetRealTimeClock()->TimeInMilliseconds();
|
||||||
if (!start_runtime_ms_) {
|
if (!start_runtime_ms_)
|
||||||
start_runtime_ms_ = now_ms;
|
start_runtime_ms_ = now_ms;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
int64_t elapsed_sec = (now_ms - *start_runtime_ms_) / 1000;
|
int64_t elapsed_sec = (now_ms - *start_runtime_ms_) / 1000;
|
||||||
return elapsed_sec > metrics::kMinRunTimeInSeconds * 2;
|
return elapsed_sec > metrics::kMinRunTimeInSeconds * 2;
|
||||||
}
|
}
|
||||||
@ -192,6 +191,7 @@ void HistogramTest::VerifyHistogramStats(bool use_rtx,
|
|||||||
EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentFramesPerSecond"));
|
EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentFramesPerSecond"));
|
||||||
EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
|
EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
|
||||||
EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
|
EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
|
||||||
|
EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
|
||||||
|
|
||||||
EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
|
EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
|
||||||
EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
|
EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
|
||||||
|
@ -114,6 +114,8 @@ ReceiveStatisticsProxy::ReceiveStatisticsProxy(
|
|||||||
avg_rtt_ms_(0),
|
avg_rtt_ms_(0),
|
||||||
last_content_type_(VideoContentType::UNSPECIFIED),
|
last_content_type_(VideoContentType::UNSPECIFIED),
|
||||||
last_codec_type_(kVideoCodecVP8),
|
last_codec_type_(kVideoCodecVP8),
|
||||||
|
num_delayed_frames_rendered_(0),
|
||||||
|
sum_missed_render_deadline_ms_(0),
|
||||||
timing_frame_info_counter_(kMovingMaxWindowMs) {
|
timing_frame_info_counter_(kMovingMaxWindowMs) {
|
||||||
decode_thread_.DetachFromThread();
|
decode_thread_.DetachFromThread();
|
||||||
network_thread_.DetachFromThread();
|
network_thread_.DetachFromThread();
|
||||||
@ -181,6 +183,19 @@ void ReceiveStatisticsProxy::UpdateHistograms() {
|
|||||||
"WebRTC.Video.DecodedFramesPerSecond",
|
"WebRTC.Video.DecodedFramesPerSecond",
|
||||||
static_cast<int>((stats_.frames_decoded * 1000.0f / elapsed_ms) +
|
static_cast<int>((stats_.frames_decoded * 1000.0f / elapsed_ms) +
|
||||||
0.5f));
|
0.5f));
|
||||||
|
|
||||||
|
const uint32_t frames_rendered = stats_.frames_rendered;
|
||||||
|
if (frames_rendered > 0) {
|
||||||
|
RTC_HISTOGRAM_PERCENTAGE("WebRTC.Video.DelayedFramesToRenderer",
|
||||||
|
static_cast<int>(num_delayed_frames_rendered_ *
|
||||||
|
100 / frames_rendered));
|
||||||
|
if (num_delayed_frames_rendered_ > 0) {
|
||||||
|
RTC_HISTOGRAM_COUNTS_1000(
|
||||||
|
"WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs",
|
||||||
|
static_cast<int>(sum_missed_render_deadline_ms_ /
|
||||||
|
num_delayed_frames_rendered_));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -742,11 +757,11 @@ void ReceiveStatisticsProxy::OnRenderedFrame(const VideoFrame& frame) {
|
|||||||
int height = frame.height();
|
int height = frame.height();
|
||||||
RTC_DCHECK_GT(width, 0);
|
RTC_DCHECK_GT(width, 0);
|
||||||
RTC_DCHECK_GT(height, 0);
|
RTC_DCHECK_GT(height, 0);
|
||||||
uint64_t now = clock_->TimeInMilliseconds();
|
int64_t now_ms = clock_->TimeInMilliseconds();
|
||||||
rtc::CritScope lock(&crit_);
|
rtc::CritScope lock(&crit_);
|
||||||
ContentSpecificStats* content_specific_stats =
|
ContentSpecificStats* content_specific_stats =
|
||||||
&content_specific_stats_[last_content_type_];
|
&content_specific_stats_[last_content_type_];
|
||||||
renders_fps_estimator_.Update(1, now);
|
renders_fps_estimator_.Update(1, now_ms);
|
||||||
++stats_.frames_rendered;
|
++stats_.frames_rendered;
|
||||||
stats_.width = width;
|
stats_.width = width;
|
||||||
stats_.height = height;
|
stats_.height = height;
|
||||||
@ -755,6 +770,13 @@ void ReceiveStatisticsProxy::OnRenderedFrame(const VideoFrame& frame) {
|
|||||||
content_specific_stats->received_width.Add(width);
|
content_specific_stats->received_width.Add(width);
|
||||||
content_specific_stats->received_height.Add(height);
|
content_specific_stats->received_height.Add(height);
|
||||||
|
|
||||||
|
// Consider taking stats_.render_delay_ms into account.
|
||||||
|
const int64_t time_until_rendering_ms = frame.render_time_ms() - now_ms;
|
||||||
|
if (time_until_rendering_ms < 0) {
|
||||||
|
sum_missed_render_deadline_ms_ += -time_until_rendering_ms;
|
||||||
|
++num_delayed_frames_rendered_;
|
||||||
|
}
|
||||||
|
|
||||||
if (frame.ntp_time_ms() > 0) {
|
if (frame.ntp_time_ms() > 0) {
|
||||||
int64_t delay_ms = clock_->CurrentNtpInMilliseconds() - frame.ntp_time_ms();
|
int64_t delay_ms = clock_->CurrentNtpInMilliseconds() - frame.ntp_time_ms();
|
||||||
if (delay_ms >= 0) {
|
if (delay_ms >= 0) {
|
||||||
|
@ -185,6 +185,8 @@ class ReceiveStatisticsProxy : public VCMReceiveStatisticsCallback,
|
|||||||
VideoCodecType last_codec_type_ RTC_GUARDED_BY(&crit_);
|
VideoCodecType last_codec_type_ RTC_GUARDED_BY(&crit_);
|
||||||
rtc::Optional<int64_t> first_decoded_frame_time_ms_ 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_);
|
rtc::Optional<int64_t> last_decoded_frame_time_ms_ RTC_GUARDED_BY(&crit_);
|
||||||
|
size_t num_delayed_frames_rendered_ RTC_GUARDED_BY(&crit_);
|
||||||
|
int64_t sum_missed_render_deadline_ms_ RTC_GUARDED_BY(&crit_);
|
||||||
// Mutable because calling Max() on MovingMaxCounter is not const. Yet it is
|
// Mutable because calling Max() on MovingMaxCounter is not const. Yet it is
|
||||||
// called from const GetStats().
|
// called from const GetStats().
|
||||||
mutable rtc::MovingMaxCounter<TimingFrameInfo> timing_frame_info_counter_
|
mutable rtc::MovingMaxCounter<TimingFrameInfo> timing_frame_info_counter_
|
||||||
|
@ -28,7 +28,6 @@ const int64_t kFreqOffsetProcessIntervalInMs = 40000;
|
|||||||
const uint32_t kLocalSsrc = 123;
|
const uint32_t kLocalSsrc = 123;
|
||||||
const uint32_t kRemoteSsrc = 456;
|
const uint32_t kRemoteSsrc = 456;
|
||||||
const int kMinRequiredSamples = 200;
|
const int kMinRequiredSamples = 200;
|
||||||
|
|
||||||
const int kWidth = 1280;
|
const int kWidth = 1280;
|
||||||
const int kHeight = 720;
|
const int kHeight = 720;
|
||||||
|
|
||||||
@ -61,7 +60,16 @@ class ReceiveStatisticsProxyTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
VideoFrame CreateFrame(int width, int height) {
|
VideoFrame CreateFrame(int width, int height) {
|
||||||
VideoFrame frame(I420Buffer::Create(width, height), 0, 0, kVideoRotation_0);
|
return CreateVideoFrame(width, height, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
VideoFrame CreateFrameWithRenderTimeMs(int64_t render_time_ms) {
|
||||||
|
return CreateVideoFrame(kWidth, kHeight, render_time_ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
VideoFrame CreateVideoFrame(int width, int height, int64_t render_time_ms) {
|
||||||
|
VideoFrame frame(I420Buffer::Create(width, height), 0, render_time_ms,
|
||||||
|
kVideoRotation_0);
|
||||||
frame.set_ntp_time_ms(fake_clock_.CurrentNtpInMilliseconds());
|
frame.set_ntp_time_ms(fake_clock_.CurrentNtpInMilliseconds());
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
@ -725,9 +733,6 @@ TEST_F(ReceiveStatisticsProxyTest, TimingHistogramsAreUpdated) {
|
|||||||
|
|
||||||
TEST_F(ReceiveStatisticsProxyTest, DoesNotReportStaleFramerates) {
|
TEST_F(ReceiveStatisticsProxyTest, DoesNotReportStaleFramerates) {
|
||||||
const int kDefaultFps = 30;
|
const int kDefaultFps = 30;
|
||||||
const int kWidth = 320;
|
|
||||||
const int kHeight = 240;
|
|
||||||
|
|
||||||
rtc::scoped_refptr<VideoFrameBuffer> video_frame_buffer(
|
rtc::scoped_refptr<VideoFrameBuffer> video_frame_buffer(
|
||||||
I420Buffer::Create(kWidth, kHeight));
|
I420Buffer::Create(kWidth, kHeight));
|
||||||
VideoFrame frame(video_frame_buffer, kVideoRotation_0, 0);
|
VideoFrame frame(video_frame_buffer, kVideoRotation_0, 0);
|
||||||
@ -752,8 +757,6 @@ TEST_F(ReceiveStatisticsProxyTest, DoesNotReportStaleFramerates) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsReceivedFrameStats) {
|
TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsReceivedFrameStats) {
|
||||||
const int kWidth = 160;
|
|
||||||
const int kHeight = 120;
|
|
||||||
EXPECT_EQ(0, statistics_proxy_->GetStats().width);
|
EXPECT_EQ(0, statistics_proxy_->GetStats().width);
|
||||||
EXPECT_EQ(0, statistics_proxy_->GetStats().height);
|
EXPECT_EQ(0, statistics_proxy_->GetStats().height);
|
||||||
EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_rendered);
|
EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_rendered);
|
||||||
@ -767,9 +770,6 @@ TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsReceivedFrameStats) {
|
|||||||
|
|
||||||
TEST_F(ReceiveStatisticsProxyTest,
|
TEST_F(ReceiveStatisticsProxyTest,
|
||||||
ReceivedFrameHistogramsAreNotUpdatedForTooFewSamples) {
|
ReceivedFrameHistogramsAreNotUpdatedForTooFewSamples) {
|
||||||
const int kWidth = 160;
|
|
||||||
const int kHeight = 120;
|
|
||||||
|
|
||||||
for (int i = 0; i < kMinRequiredSamples - 1; ++i)
|
for (int i = 0; i < kMinRequiredSamples - 1; ++i)
|
||||||
statistics_proxy_->OnRenderedFrame(CreateFrame(kWidth, kHeight));
|
statistics_proxy_->OnRenderedFrame(CreateFrame(kWidth, kHeight));
|
||||||
|
|
||||||
@ -781,9 +781,6 @@ TEST_F(ReceiveStatisticsProxyTest,
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ReceiveStatisticsProxyTest, ReceivedFrameHistogramsAreUpdated) {
|
TEST_F(ReceiveStatisticsProxyTest, ReceivedFrameHistogramsAreUpdated) {
|
||||||
const int kWidth = 160;
|
|
||||||
const int kHeight = 120;
|
|
||||||
|
|
||||||
for (int i = 0; i < kMinRequiredSamples; ++i)
|
for (int i = 0; i < kMinRequiredSamples; ++i)
|
||||||
statistics_proxy_->OnRenderedFrame(CreateFrame(kWidth, kHeight));
|
statistics_proxy_->OnRenderedFrame(CreateFrame(kWidth, kHeight));
|
||||||
|
|
||||||
@ -798,6 +795,95 @@ TEST_F(ReceiveStatisticsProxyTest, ReceivedFrameHistogramsAreUpdated) {
|
|||||||
metrics::NumEvents("WebRTC.Video.ReceivedHeightInPixels", kHeight));
|
metrics::NumEvents("WebRTC.Video.ReceivedHeightInPixels", kHeight));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(ReceiveStatisticsProxyTest, ZeroDelayReportedIfFrameNotDelayed) {
|
||||||
|
statistics_proxy_->OnDecodedFrame(rtc::nullopt, kWidth, kHeight,
|
||||||
|
VideoContentType::UNSPECIFIED);
|
||||||
|
|
||||||
|
// Frame not delayed, delayed frames to render: 0%.
|
||||||
|
const int64_t kNowMs = fake_clock_.TimeInMilliseconds();
|
||||||
|
statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs));
|
||||||
|
|
||||||
|
// Min run time has passed.
|
||||||
|
fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000));
|
||||||
|
statistics_proxy_.reset();
|
||||||
|
EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
|
||||||
|
EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer", 0));
|
||||||
|
EXPECT_EQ(0, metrics::NumSamples(
|
||||||
|
"WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ReceiveStatisticsProxyTest,
|
||||||
|
DelayedFrameHistogramsAreNotUpdatedIfMinRuntimeHasNotPassed) {
|
||||||
|
statistics_proxy_->OnDecodedFrame(rtc::nullopt, kWidth, kHeight,
|
||||||
|
VideoContentType::UNSPECIFIED);
|
||||||
|
|
||||||
|
// Frame not delayed, delayed frames to render: 0%.
|
||||||
|
const int64_t kNowMs = fake_clock_.TimeInMilliseconds();
|
||||||
|
statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs));
|
||||||
|
|
||||||
|
// Min run time has not passed.
|
||||||
|
fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000) -
|
||||||
|
1);
|
||||||
|
statistics_proxy_.reset();
|
||||||
|
EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
|
||||||
|
EXPECT_EQ(0, metrics::NumSamples(
|
||||||
|
"WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ReceiveStatisticsProxyTest,
|
||||||
|
DelayedFramesHistogramsAreNotUpdatedIfNoRenderedFrames) {
|
||||||
|
statistics_proxy_->OnDecodedFrame(rtc::nullopt, kWidth, kHeight,
|
||||||
|
VideoContentType::UNSPECIFIED);
|
||||||
|
|
||||||
|
// Min run time has passed. No rendered frames.
|
||||||
|
fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000));
|
||||||
|
statistics_proxy_.reset();
|
||||||
|
EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
|
||||||
|
EXPECT_EQ(0, metrics::NumSamples(
|
||||||
|
"WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ReceiveStatisticsProxyTest, DelayReportedIfFrameIsDelayed) {
|
||||||
|
statistics_proxy_->OnDecodedFrame(rtc::nullopt, kWidth, kHeight,
|
||||||
|
VideoContentType::UNSPECIFIED);
|
||||||
|
|
||||||
|
// Frame delayed 1 ms, delayed frames to render: 100%.
|
||||||
|
const int64_t kNowMs = fake_clock_.TimeInMilliseconds();
|
||||||
|
statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs - 1));
|
||||||
|
|
||||||
|
// Min run time has passed.
|
||||||
|
fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000));
|
||||||
|
statistics_proxy_.reset();
|
||||||
|
EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
|
||||||
|
EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer", 100));
|
||||||
|
EXPECT_EQ(1, metrics::NumSamples(
|
||||||
|
"WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
|
||||||
|
EXPECT_EQ(1, metrics::NumEvents(
|
||||||
|
"WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs", 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ReceiveStatisticsProxyTest, AverageDelayOfDelayedFramesIsReported) {
|
||||||
|
statistics_proxy_->OnDecodedFrame(rtc::nullopt, kWidth, kHeight,
|
||||||
|
VideoContentType::UNSPECIFIED);
|
||||||
|
|
||||||
|
// Two frames delayed (6 ms, 10 ms), delayed frames to render: 50%.
|
||||||
|
const int64_t kNowMs = fake_clock_.TimeInMilliseconds();
|
||||||
|
statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs - 10));
|
||||||
|
statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs - 6));
|
||||||
|
statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs));
|
||||||
|
statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs + 1));
|
||||||
|
|
||||||
|
// Min run time has passed.
|
||||||
|
fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000));
|
||||||
|
statistics_proxy_.reset();
|
||||||
|
EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
|
||||||
|
EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer", 50));
|
||||||
|
EXPECT_EQ(1, metrics::NumSamples(
|
||||||
|
"WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
|
||||||
|
EXPECT_EQ(1, metrics::NumEvents(
|
||||||
|
"WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs", 8));
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(ReceiveStatisticsProxyTest,
|
TEST_F(ReceiveStatisticsProxyTest,
|
||||||
RtcpHistogramsNotUpdatedIfMinRuntimeHasNotPassed) {
|
RtcpHistogramsNotUpdatedIfMinRuntimeHasNotPassed) {
|
||||||
InsertFirstRtpPacket(kRemoteSsrc);
|
InsertFirstRtpPacket(kRemoteSsrc);
|
||||||
|
Reference in New Issue
Block a user