blob: b8a96b2f5e824248351285606e093acf65e018c2 [file] [log] [blame]
sakale5ba44e2016-10-26 07:09:24 -07001/*
2 * Copyright 2016 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "video/receive_statistics_proxy.h"
sakale5ba44e2016-10-26 07:09:24 -070012
asapersson2077f2f2017-05-11 05:37:35 -070013#include <limits>
sakale5ba44e2016-10-26 07:09:24 -070014#include <memory>
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +020015#include <utility>
sakale5ba44e2016-10-26 07:09:24 -070016
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "api/video/i420_buffer.h"
18#include "api/video/video_frame.h"
19#include "api/video/video_rotation.h"
20#include "modules/video_coding/include/video_codec_interface.h"
21#include "system_wrappers/include/metrics.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020022#include "test/gtest.h"
sakale5ba44e2016-10-26 07:09:24 -070023
24namespace webrtc {
asaperssonde9e5ff2016-11-02 07:14:03 -070025namespace {
26const int64_t kFreqOffsetProcessIntervalInMs = 40000;
asapersson46c4e3c2016-11-03 06:48:19 -070027const uint32_t kLocalSsrc = 123;
28const uint32_t kRemoteSsrc = 456;
29const int kMinRequiredSamples = 200;
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +020030const int kWidth = 1280;
31const int kHeight = 720;
32
asaperssonde9e5ff2016-11-02 07:14:03 -070033} // namespace
sakale5ba44e2016-10-26 07:09:24 -070034
35// TODO(sakal): ReceiveStatisticsProxy is lacking unittesting.
sprang892dab52017-08-15 05:00:33 -070036class ReceiveStatisticsProxyTest
37 : public ::testing::TestWithParam<webrtc::VideoContentType> {
sakale5ba44e2016-10-26 07:09:24 -070038 public:
39 ReceiveStatisticsProxyTest() : fake_clock_(1234), config_(GetTestConfig()) {}
40 virtual ~ReceiveStatisticsProxyTest() {}
41
42 protected:
43 virtual void SetUp() {
asaperssonde9e5ff2016-11-02 07:14:03 -070044 metrics::Reset();
sakale5ba44e2016-10-26 07:09:24 -070045 statistics_proxy_.reset(new ReceiveStatisticsProxy(&config_, &fake_clock_));
46 }
47
48 VideoReceiveStream::Config GetTestConfig() {
49 VideoReceiveStream::Config config(nullptr);
asapersson46c4e3c2016-11-03 06:48:19 -070050 config.rtp.local_ssrc = kLocalSsrc;
51 config.rtp.remote_ssrc = kRemoteSsrc;
sakale5ba44e2016-10-26 07:09:24 -070052 return config;
53 }
54
asapersson2077f2f2017-05-11 05:37:35 -070055 void InsertFirstRtpPacket(uint32_t ssrc) {
56 StreamDataCounters counters;
57 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
58 statistics_proxy_->DataCountersUpdated(counters, ssrc);
59 }
60
61 VideoFrame CreateFrame(int width, int height) {
Åsa Persson81327d52018-06-05 13:34:33 +020062 return CreateVideoFrame(width, height, 0);
63 }
64
65 VideoFrame CreateFrameWithRenderTimeMs(int64_t render_time_ms) {
66 return CreateVideoFrame(kWidth, kHeight, render_time_ms);
67 }
68
69 VideoFrame CreateVideoFrame(int width, int height, int64_t render_time_ms) {
70 VideoFrame frame(I420Buffer::Create(width, height), 0, render_time_ms,
71 kVideoRotation_0);
asapersson2077f2f2017-05-11 05:37:35 -070072 frame.set_ntp_time_ms(fake_clock_.CurrentNtpInMilliseconds());
73 return frame;
74 }
75
sakale5ba44e2016-10-26 07:09:24 -070076 SimulatedClock fake_clock_;
asaperssonde9e5ff2016-11-02 07:14:03 -070077 const VideoReceiveStream::Config config_;
sakale5ba44e2016-10-26 07:09:24 -070078 std::unique_ptr<ReceiveStatisticsProxy> statistics_proxy_;
sakale5ba44e2016-10-26 07:09:24 -070079};
80
81TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameIncreasesFramesDecoded) {
82 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_decoded);
83 for (uint32_t i = 1; i <= 3; ++i) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +020084 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
ilnik00d802b2017-04-11 10:34:31 -070085 VideoContentType::UNSPECIFIED);
sakale5ba44e2016-10-26 07:09:24 -070086 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_decoded);
87 }
88}
89
Åsa Perssonb9b07ea2018-01-24 17:04:07 +010090TEST_F(ReceiveStatisticsProxyTest, DecodedFpsIsReported) {
91 const int kFps = 20;
92 const int kRequiredSamples = metrics::kMinRunTimeInSeconds * kFps;
93 for (int i = 0; i < kRequiredSamples; ++i) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +020094 statistics_proxy_->OnDecodedFrame(absl::optional<uint8_t>(), kWidth,
95 kHeight, VideoContentType::UNSPECIFIED);
Åsa Perssonb9b07ea2018-01-24 17:04:07 +010096 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
97 }
98 statistics_proxy_.reset();
99 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
100 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DecodedFramesPerSecond", kFps));
101}
102
103TEST_F(ReceiveStatisticsProxyTest, DecodedFpsIsNotReportedForTooFewSamples) {
104 const int kFps = 20;
105 const int kRequiredSamples = metrics::kMinRunTimeInSeconds * kFps;
106 for (int i = 0; i < kRequiredSamples - 1; ++i) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200107 statistics_proxy_->OnDecodedFrame(absl::optional<uint8_t>(), kWidth,
108 kHeight, VideoContentType::UNSPECIFIED);
Åsa Perssonb9b07ea2018-01-24 17:04:07 +0100109 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
110 }
111 statistics_proxy_.reset();
112 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
113}
114
115TEST_F(ReceiveStatisticsProxyTest, DecodedFpsIsReportedWithQpReset) {
116 const int kFps1 = 10;
117 for (int i = 0; i < metrics::kMinRunTimeInSeconds * kFps1; ++i) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200118 statistics_proxy_->OnDecodedFrame(absl::optional<uint8_t>(), kWidth,
119 kHeight, VideoContentType::UNSPECIFIED);
Åsa Perssonb9b07ea2018-01-24 17:04:07 +0100120 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps1);
121 }
122 // First QP value received, resets frames decoded.
123 const int kFps2 = 20;
124 for (int i = 0; i < metrics::kMinRunTimeInSeconds * kFps2; ++i) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200125 statistics_proxy_->OnDecodedFrame(absl::optional<uint8_t>(1u), kWidth,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200126 kHeight, VideoContentType::UNSPECIFIED);
Åsa Perssonb9b07ea2018-01-24 17:04:07 +0100127 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps2);
128 }
129 statistics_proxy_.reset();
130 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
131 EXPECT_EQ(1,
132 metrics::NumEvents("WebRTC.Video.DecodedFramesPerSecond", kFps2));
133}
134
sakalcc452e12017-02-09 04:53:45 -0800135TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameWithQpResetsFramesDecoded) {
136 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_decoded);
137 for (uint32_t i = 1; i <= 3; ++i) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200138 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
ilnik00d802b2017-04-11 10:34:31 -0700139 VideoContentType::UNSPECIFIED);
sakalcc452e12017-02-09 04:53:45 -0800140 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_decoded);
141 }
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200142 statistics_proxy_->OnDecodedFrame(1u, kWidth, kHeight,
143 VideoContentType::UNSPECIFIED);
sakalcc452e12017-02-09 04:53:45 -0800144 EXPECT_EQ(1u, statistics_proxy_->GetStats().frames_decoded);
145}
146
147TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameIncreasesQpSum) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200148 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200149 statistics_proxy_->OnDecodedFrame(3u, kWidth, kHeight,
150 VideoContentType::UNSPECIFIED);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100151 EXPECT_EQ(3u, statistics_proxy_->GetStats().qp_sum);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200152 statistics_proxy_->OnDecodedFrame(127u, kWidth, kHeight,
153 VideoContentType::UNSPECIFIED);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100154 EXPECT_EQ(130u, statistics_proxy_->GetStats().qp_sum);
sakalcc452e12017-02-09 04:53:45 -0800155}
156
ilnik2e1b40b2017-09-04 07:57:17 -0700157TEST_F(ReceiveStatisticsProxyTest, ReportsContentType) {
158 const std::string kRealtimeString("realtime");
159 const std::string kScreenshareString("screen");
160 EXPECT_EQ(kRealtimeString, videocontenttypehelpers::ToString(
161 statistics_proxy_->GetStats().content_type));
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200162 statistics_proxy_->OnDecodedFrame(3u, kWidth, kHeight,
163 VideoContentType::SCREENSHARE);
ilnik2e1b40b2017-09-04 07:57:17 -0700164 EXPECT_EQ(kScreenshareString, videocontenttypehelpers::ToString(
165 statistics_proxy_->GetStats().content_type));
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200166 statistics_proxy_->OnDecodedFrame(3u, kWidth, kHeight,
167 VideoContentType::UNSPECIFIED);
ilnik2e1b40b2017-09-04 07:57:17 -0700168 EXPECT_EQ(kRealtimeString, videocontenttypehelpers::ToString(
169 statistics_proxy_->GetStats().content_type));
170}
171
ilnika79cc282017-08-23 05:24:10 -0700172TEST_F(ReceiveStatisticsProxyTest, ReportsMaxInterframeDelay) {
173 const int64_t kInterframeDelayMs1 = 100;
174 const int64_t kInterframeDelayMs2 = 200;
175 const int64_t kInterframeDelayMs3 = 100;
176 EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200177 statistics_proxy_->OnDecodedFrame(3u, kWidth, kHeight,
178 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700179 EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
ilnikf04afde2017-07-07 01:26:24 -0700180
181 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs1);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200182 statistics_proxy_->OnDecodedFrame(127u, kWidth, kHeight,
183 VideoContentType::UNSPECIFIED);
ilnikf04afde2017-07-07 01:26:24 -0700184 EXPECT_EQ(kInterframeDelayMs1,
ilnika79cc282017-08-23 05:24:10 -0700185 statistics_proxy_->GetStats().interframe_delay_max_ms);
ilnikf04afde2017-07-07 01:26:24 -0700186
187 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs2);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200188 statistics_proxy_->OnDecodedFrame(127u, kWidth, kHeight,
189 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700190 EXPECT_EQ(kInterframeDelayMs2,
191 statistics_proxy_->GetStats().interframe_delay_max_ms);
192
193 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs3);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200194 statistics_proxy_->OnDecodedFrame(127u, kWidth, kHeight,
195 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700196 // kInterframeDelayMs3 is smaller than kInterframeDelayMs2.
197 EXPECT_EQ(kInterframeDelayMs2,
198 statistics_proxy_->GetStats().interframe_delay_max_ms);
199}
200
201TEST_F(ReceiveStatisticsProxyTest, ReportInterframeDelayInWindow) {
Ilya Nikolaevskiyb06b3582017-10-16 17:59:12 +0200202 const int64_t kInterframeDelayMs1 = 900;
203 const int64_t kInterframeDelayMs2 = 750;
204 const int64_t kInterframeDelayMs3 = 700;
ilnika79cc282017-08-23 05:24:10 -0700205 EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200206 statistics_proxy_->OnDecodedFrame(3u, kWidth, kHeight,
207 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700208 EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
209
210 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs1);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200211 statistics_proxy_->OnDecodedFrame(127u, kWidth, kHeight,
212 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700213 EXPECT_EQ(kInterframeDelayMs1,
214 statistics_proxy_->GetStats().interframe_delay_max_ms);
215
216 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs2);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200217 statistics_proxy_->OnDecodedFrame(127u, kWidth, kHeight,
218 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700219 // Still first delay is the maximum
220 EXPECT_EQ(kInterframeDelayMs1,
221 statistics_proxy_->GetStats().interframe_delay_max_ms);
222
223 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs3);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200224 statistics_proxy_->OnDecodedFrame(127u, kWidth, kHeight,
225 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700226 // Now the first sample is out of the window, so the second is the maximum.
227 EXPECT_EQ(kInterframeDelayMs2,
228 statistics_proxy_->GetStats().interframe_delay_max_ms);
ilnikf04afde2017-07-07 01:26:24 -0700229}
230
sakalcc452e12017-02-09 04:53:45 -0800231TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameWithoutQpQpSumWontExist) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200232 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
233 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
ilnik00d802b2017-04-11 10:34:31 -0700234 VideoContentType::UNSPECIFIED);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200235 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakalcc452e12017-02-09 04:53:45 -0800236}
237
238TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameWithoutQpResetsQpSum) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200239 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200240 statistics_proxy_->OnDecodedFrame(3u, kWidth, kHeight,
241 VideoContentType::UNSPECIFIED);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100242 EXPECT_EQ(3u, statistics_proxy_->GetStats().qp_sum);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200243 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
ilnik00d802b2017-04-11 10:34:31 -0700244 VideoContentType::UNSPECIFIED);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200245 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakalcc452e12017-02-09 04:53:45 -0800246}
247
hbos50cfe1f2017-01-23 07:21:55 -0800248TEST_F(ReceiveStatisticsProxyTest, OnRenderedFrameIncreasesFramesRendered) {
249 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_rendered);
ilnik00d802b2017-04-11 10:34:31 -0700250 webrtc::VideoFrame frame(webrtc::I420Buffer::Create(1, 1), 0, 0,
251 webrtc::kVideoRotation_0);
hbos50cfe1f2017-01-23 07:21:55 -0800252 for (uint32_t i = 1; i <= 3; ++i) {
253 statistics_proxy_->OnRenderedFrame(frame);
254 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_rendered);
255 }
256}
257
asapersson46c4e3c2016-11-03 06:48:19 -0700258TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsSsrc) {
259 EXPECT_EQ(kRemoteSsrc, statistics_proxy_->GetStats().ssrc);
260}
261
262TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsIncomingPayloadType) {
263 const int kPayloadType = 111;
264 statistics_proxy_->OnIncomingPayloadType(kPayloadType);
265 EXPECT_EQ(kPayloadType, statistics_proxy_->GetStats().current_payload_type);
266}
267
asapersson6966bd52017-01-03 00:44:06 -0800268TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsDecoderImplementationName) {
269 const char* kName = "decoderName";
270 statistics_proxy_->OnDecoderImplementationName(kName);
271 EXPECT_STREQ(
272 kName, statistics_proxy_->GetStats().decoder_implementation_name.c_str());
273}
274
philipela45102f2017-02-22 05:30:39 -0800275TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsOnCompleteFrame) {
276 const int kFrameSizeBytes = 1000;
ilnik6d5b4d62017-08-30 03:32:14 -0700277 statistics_proxy_->OnCompleteFrame(true, kFrameSizeBytes,
278 VideoContentType::UNSPECIFIED);
philipela45102f2017-02-22 05:30:39 -0800279 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
280 EXPECT_EQ(1, stats.network_frame_rate);
philipela45102f2017-02-22 05:30:39 -0800281 EXPECT_EQ(1, stats.frame_counts.key_frames);
282 EXPECT_EQ(0, stats.frame_counts.delta_frames);
asapersson46c4e3c2016-11-03 06:48:19 -0700283}
284
285TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsDecodeTimingStats) {
286 const int kDecodeMs = 1;
287 const int kMaxDecodeMs = 2;
288 const int kCurrentDelayMs = 3;
289 const int kTargetDelayMs = 4;
290 const int kJitterBufferMs = 5;
291 const int kMinPlayoutDelayMs = 6;
292 const int kRenderDelayMs = 7;
293 const int64_t kRttMs = 8;
philipela45102f2017-02-22 05:30:39 -0800294 statistics_proxy_->OnRttUpdate(kRttMs, 0);
295 statistics_proxy_->OnFrameBufferTimingsUpdated(
asapersson46c4e3c2016-11-03 06:48:19 -0700296 kDecodeMs, kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs, kJitterBufferMs,
philipela45102f2017-02-22 05:30:39 -0800297 kMinPlayoutDelayMs, kRenderDelayMs);
asapersson46c4e3c2016-11-03 06:48:19 -0700298 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
299 EXPECT_EQ(kDecodeMs, stats.decode_ms);
300 EXPECT_EQ(kMaxDecodeMs, stats.max_decode_ms);
301 EXPECT_EQ(kCurrentDelayMs, stats.current_delay_ms);
302 EXPECT_EQ(kTargetDelayMs, stats.target_delay_ms);
303 EXPECT_EQ(kJitterBufferMs, stats.jitter_buffer_ms);
304 EXPECT_EQ(kMinPlayoutDelayMs, stats.min_playout_delay_ms);
305 EXPECT_EQ(kRenderDelayMs, stats.render_delay_ms);
306}
307
asapersson6966bd52017-01-03 00:44:06 -0800308TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsRtcpPacketTypeCounts) {
309 const uint32_t kFirPackets = 33;
310 const uint32_t kPliPackets = 44;
311 const uint32_t kNackPackets = 55;
312 RtcpPacketTypeCounter counter;
313 counter.fir_packets = kFirPackets;
314 counter.pli_packets = kPliPackets;
315 counter.nack_packets = kNackPackets;
316 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc, counter);
317 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
318 EXPECT_EQ(kFirPackets, stats.rtcp_packet_type_counts.fir_packets);
319 EXPECT_EQ(kPliPackets, stats.rtcp_packet_type_counts.pli_packets);
320 EXPECT_EQ(kNackPackets, stats.rtcp_packet_type_counts.nack_packets);
321}
322
323TEST_F(ReceiveStatisticsProxyTest,
324 GetStatsReportsNoRtcpPacketTypeCountsForUnknownSsrc) {
325 RtcpPacketTypeCounter counter;
326 counter.fir_packets = 33;
327 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc + 1, counter);
328 EXPECT_EQ(0u,
329 statistics_proxy_->GetStats().rtcp_packet_type_counts.fir_packets);
330}
331
332TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsFrameCounts) {
333 const int kKeyFrames = 3;
334 const int kDeltaFrames = 22;
335 FrameCounts frame_counts;
336 frame_counts.key_frames = kKeyFrames;
337 frame_counts.delta_frames = kDeltaFrames;
338 statistics_proxy_->OnFrameCountsUpdated(frame_counts);
339 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
340 EXPECT_EQ(kKeyFrames, stats.frame_counts.key_frames);
341 EXPECT_EQ(kDeltaFrames, stats.frame_counts.delta_frames);
342}
343
asapersson46c4e3c2016-11-03 06:48:19 -0700344TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsDiscardedPackets) {
345 const int kDiscardedPackets = 12;
346 statistics_proxy_->OnDiscardedPacketsUpdated(kDiscardedPackets);
347 EXPECT_EQ(kDiscardedPackets, statistics_proxy_->GetStats().discarded_packets);
348}
349
asapersson6966bd52017-01-03 00:44:06 -0800350TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsRtcpStats) {
351 const uint8_t kFracLost = 0;
Harald Alvestrandc7c41912017-12-08 09:59:34 +0100352 const int32_t kCumLost = 1;
asapersson6966bd52017-01-03 00:44:06 -0800353 const uint32_t kExtSeqNum = 10;
354 const uint32_t kJitter = 4;
355
356 RtcpStatistics rtcp_stats;
357 rtcp_stats.fraction_lost = kFracLost;
srte186d9c32017-08-04 05:03:53 -0700358 rtcp_stats.packets_lost = kCumLost;
359 rtcp_stats.extended_highest_sequence_number = kExtSeqNum;
asapersson6966bd52017-01-03 00:44:06 -0800360 rtcp_stats.jitter = kJitter;
361 statistics_proxy_->StatisticsUpdated(rtcp_stats, kRemoteSsrc);
362
363 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
364 EXPECT_EQ(kFracLost, stats.rtcp_stats.fraction_lost);
srte186d9c32017-08-04 05:03:53 -0700365 EXPECT_EQ(kCumLost, stats.rtcp_stats.packets_lost);
366 EXPECT_EQ(kExtSeqNum, stats.rtcp_stats.extended_highest_sequence_number);
asapersson6966bd52017-01-03 00:44:06 -0800367 EXPECT_EQ(kJitter, stats.rtcp_stats.jitter);
368}
369
370TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsCName) {
371 const char* kName = "cName";
372 statistics_proxy_->CNameChanged(kName, kRemoteSsrc);
373 EXPECT_STREQ(kName, statistics_proxy_->GetStats().c_name.c_str());
374}
375
376TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsNoCNameForUnknownSsrc) {
377 const char* kName = "cName";
378 statistics_proxy_->CNameChanged(kName, kRemoteSsrc + 1);
379 EXPECT_STREQ("", statistics_proxy_->GetStats().c_name.c_str());
380}
381
ilnik2edc6842017-07-06 03:06:50 -0700382TEST_F(ReceiveStatisticsProxyTest,
ilnik75204c52017-09-04 03:35:40 -0700383 ReportsLongestTimingFrameInfo) {
ilnik2edc6842017-07-06 03:06:50 -0700384 const int64_t kShortEndToEndDelay = 10;
385 const int64_t kMedEndToEndDelay = 20;
386 const int64_t kLongEndToEndDelay = 100;
387 const uint32_t kExpectedRtpTimestamp = 2;
388 TimingFrameInfo info;
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200389 absl::optional<TimingFrameInfo> result;
ilnik2edc6842017-07-06 03:06:50 -0700390 info.rtp_timestamp = kExpectedRtpTimestamp - 1;
391 info.capture_time_ms = 0;
392 info.decode_finish_ms = kShortEndToEndDelay;
393 statistics_proxy_->OnTimingFrameInfoUpdated(info);
394 info.rtp_timestamp =
395 kExpectedRtpTimestamp; // this frame should be reported in the end.
396 info.capture_time_ms = 0;
397 info.decode_finish_ms = kLongEndToEndDelay;
398 statistics_proxy_->OnTimingFrameInfoUpdated(info);
399 info.rtp_timestamp = kExpectedRtpTimestamp + 1;
400 info.capture_time_ms = 0;
401 info.decode_finish_ms = kMedEndToEndDelay;
402 statistics_proxy_->OnTimingFrameInfoUpdated(info);
ilnik75204c52017-09-04 03:35:40 -0700403 result = statistics_proxy_->GetStats().timing_frame_info;
ilnik2edc6842017-07-06 03:06:50 -0700404 EXPECT_TRUE(result);
405 EXPECT_EQ(kExpectedRtpTimestamp, result->rtp_timestamp);
406}
407
ilnik75204c52017-09-04 03:35:40 -0700408TEST_F(ReceiveStatisticsProxyTest, RespectsReportingIntervalForTimingFrames) {
409 TimingFrameInfo info;
ilnik2edc6842017-07-06 03:06:50 -0700410 const int64_t kShortEndToEndDelay = 10;
411 const uint32_t kExpectedRtpTimestamp = 2;
ilnik75204c52017-09-04 03:35:40 -0700412 const int64_t kShortDelayMs = 1000;
413 const int64_t kLongDelayMs = 10000;
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200414 absl::optional<TimingFrameInfo> result;
ilnik2edc6842017-07-06 03:06:50 -0700415 info.rtp_timestamp = kExpectedRtpTimestamp;
416 info.capture_time_ms = 0;
417 info.decode_finish_ms = kShortEndToEndDelay;
418 statistics_proxy_->OnTimingFrameInfoUpdated(info);
ilnik75204c52017-09-04 03:35:40 -0700419 fake_clock_.AdvanceTimeMilliseconds(kShortDelayMs);
420 result = statistics_proxy_->GetStats().timing_frame_info;
ilnik2edc6842017-07-06 03:06:50 -0700421 EXPECT_TRUE(result);
422 EXPECT_EQ(kExpectedRtpTimestamp, result->rtp_timestamp);
ilnik75204c52017-09-04 03:35:40 -0700423 fake_clock_.AdvanceTimeMilliseconds(kLongDelayMs);
424 result = statistics_proxy_->GetStats().timing_frame_info;
ilnik2edc6842017-07-06 03:06:50 -0700425 EXPECT_FALSE(result);
426}
427
asapersson46c4e3c2016-11-03 06:48:19 -0700428TEST_F(ReceiveStatisticsProxyTest, LifetimeHistogramIsUpdated) {
429 const int64_t kTimeSec = 3;
430 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
ilnik6d5b4d62017-08-30 03:32:14 -0700431 // Need at least one frame to report stream lifetime.
432 statistics_proxy_->OnCompleteFrame(true, 1000, VideoContentType::UNSPECIFIED);
asapersson46c4e3c2016-11-03 06:48:19 -0700433 // Histograms are updated when the statistics_proxy_ is deleted.
434 statistics_proxy_.reset();
435 EXPECT_EQ(1,
436 metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
437 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.ReceiveStreamLifetimeInSeconds",
438 kTimeSec));
439}
440
ilnik6d5b4d62017-08-30 03:32:14 -0700441TEST_F(ReceiveStatisticsProxyTest,
442 LifetimeHistogramNotReportedForEmptyStreams) {
443 const int64_t kTimeSec = 3;
444 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
445 // No frames received.
446 // Histograms are updated when the statistics_proxy_ is deleted.
447 statistics_proxy_.reset();
448 EXPECT_EQ(0,
449 metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
450}
451
palmkvista40672a2017-01-13 05:58:34 -0800452TEST_F(ReceiveStatisticsProxyTest, BadCallHistogramsAreUpdated) {
453 // Based on the tuning parameters this will produce 7 uncertain states,
454 // then 10 certainly bad states. There has to be 10 certain states before
455 // any histograms are recorded.
456 const int kNumBadSamples = 17;
457
458 StreamDataCounters counters;
459 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
460 statistics_proxy_->DataCountersUpdated(counters, config_.rtp.remote_ssrc);
461
462 for (int i = 0; i < kNumBadSamples; ++i) {
463 // Since OnRenderedFrame is never called the fps in each sample will be 0,
464 // i.e. bad
465 fake_clock_.AdvanceTimeMilliseconds(1000);
466 statistics_proxy_->OnIncomingRate(0, 0);
467 }
468 // Histograms are updated when the statistics_proxy_ is deleted.
469 statistics_proxy_.reset();
470 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BadCall.Any"));
471 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BadCall.Any", 100));
472
473 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BadCall.FrameRate"));
474 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BadCall.FrameRate", 100));
475
476 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.BadCall.FrameRateVariance"));
477
478 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.BadCall.Qp"));
479}
480
asapersson0c43f772016-11-30 01:42:26 -0800481TEST_F(ReceiveStatisticsProxyTest, PacketLossHistogramIsUpdated) {
482 const uint32_t kCumLost1 = 1;
483 const uint32_t kExtSeqNum1 = 10;
484 const uint32_t kCumLost2 = 2;
485 const uint32_t kExtSeqNum2 = 20;
486
487 // One report block received.
488 RtcpStatistics rtcp_stats1;
srte186d9c32017-08-04 05:03:53 -0700489 rtcp_stats1.packets_lost = kCumLost1;
490 rtcp_stats1.extended_highest_sequence_number = kExtSeqNum1;
asapersson0c43f772016-11-30 01:42:26 -0800491 statistics_proxy_->StatisticsUpdated(rtcp_stats1, kRemoteSsrc);
492
493 // Two report blocks received.
494 RtcpStatistics rtcp_stats2;
srte186d9c32017-08-04 05:03:53 -0700495 rtcp_stats2.packets_lost = kCumLost2;
496 rtcp_stats2.extended_highest_sequence_number = kExtSeqNum2;
asapersson0c43f772016-11-30 01:42:26 -0800497 statistics_proxy_->StatisticsUpdated(rtcp_stats2, kRemoteSsrc);
498
499 // Two received report blocks but min run time has not passed.
500 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
501 SetUp(); // Reset stat proxy causes histograms to be updated.
502 EXPECT_EQ(0,
503 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
504
505 // Two report blocks received.
506 statistics_proxy_->StatisticsUpdated(rtcp_stats1, kRemoteSsrc);
507 statistics_proxy_->StatisticsUpdated(rtcp_stats2, kRemoteSsrc);
508
509 // Two received report blocks and min run time has passed.
510 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
511 SetUp();
512 EXPECT_EQ(1,
513 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
514 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.ReceivedPacketsLostInPercent",
515 (kCumLost2 - kCumLost1) * 100 /
516 (kExtSeqNum2 - kExtSeqNum1)));
517}
518
519TEST_F(ReceiveStatisticsProxyTest,
520 PacketLossHistogramIsNotUpdatedIfLessThanTwoReportBlocksAreReceived) {
521 RtcpStatistics rtcp_stats1;
srte186d9c32017-08-04 05:03:53 -0700522 rtcp_stats1.packets_lost = 1;
523 rtcp_stats1.extended_highest_sequence_number = 10;
asapersson0c43f772016-11-30 01:42:26 -0800524
525 // Min run time has passed but no received report block.
526 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
527 SetUp(); // Reset stat proxy causes histograms to be updated.
528 EXPECT_EQ(0,
529 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
530
531 // Min run time has passed but only one received report block.
532 statistics_proxy_->StatisticsUpdated(rtcp_stats1, kRemoteSsrc);
533 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
534 SetUp();
535 EXPECT_EQ(0,
536 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
537}
538
asapersson2077f2f2017-05-11 05:37:35 -0700539TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsAvSyncOffset) {
540 const int64_t kSyncOffsetMs = 22;
541 const double kFreqKhz = 90.0;
542 EXPECT_EQ(std::numeric_limits<int>::max(),
543 statistics_proxy_->GetStats().sync_offset_ms);
544 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
545 EXPECT_EQ(kSyncOffsetMs, statistics_proxy_->GetStats().sync_offset_ms);
546}
547
asapersson46c4e3c2016-11-03 06:48:19 -0700548TEST_F(ReceiveStatisticsProxyTest, AvSyncOffsetHistogramIsUpdated) {
549 const int64_t kSyncOffsetMs = 22;
550 const double kFreqKhz = 90.0;
551 for (int i = 0; i < kMinRequiredSamples; ++i)
552 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
553 // Histograms are updated when the statistics_proxy_ is deleted.
554 statistics_proxy_.reset();
555 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AVSyncOffsetInMs"));
556 EXPECT_EQ(1,
557 metrics::NumEvents("WebRTC.Video.AVSyncOffsetInMs", kSyncOffsetMs));
558}
559
asaperssonde9e5ff2016-11-02 07:14:03 -0700560TEST_F(ReceiveStatisticsProxyTest, RtpToNtpFrequencyOffsetHistogramIsUpdated) {
561 const int64_t kSyncOffsetMs = 22;
562 const double kFreqKhz = 90.0;
563 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
564 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz + 2.2);
565 fake_clock_.AdvanceTimeMilliseconds(kFreqOffsetProcessIntervalInMs);
566 // Process interval passed, max diff: 2.
567 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz + 1.1);
568 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz - 4.2);
569 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz - 0.9);
570 fake_clock_.AdvanceTimeMilliseconds(kFreqOffsetProcessIntervalInMs);
571 // Process interval passed, max diff: 4.
572 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
573 statistics_proxy_.reset();
574 // Average reported: (2 + 4) / 2 = 3.
575 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtpToNtpFreqOffsetInKhz"));
576 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtpToNtpFreqOffsetInKhz", 3));
577}
578
asapersson6966bd52017-01-03 00:44:06 -0800579TEST_F(ReceiveStatisticsProxyTest, Vp8QpHistogramIsUpdated) {
580 const int kQp = 22;
asapersson6966bd52017-01-03 00:44:06 -0800581
582 for (int i = 0; i < kMinRequiredSamples; ++i)
Niels Möller147013a2018-10-01 15:56:33 +0200583 statistics_proxy_->OnPreDecode(kVideoCodecVP8, kQp);
asapersson6966bd52017-01-03 00:44:06 -0800584
585 statistics_proxy_.reset();
586 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
587 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Decoded.Vp8.Qp", kQp));
588}
589
590TEST_F(ReceiveStatisticsProxyTest, Vp8QpHistogramIsNotUpdatedForTooFewSamples) {
Niels Möller147013a2018-10-01 15:56:33 +0200591 const int kQp = 22;
asapersson6966bd52017-01-03 00:44:06 -0800592
593 for (int i = 0; i < kMinRequiredSamples - 1; ++i)
Niels Möller147013a2018-10-01 15:56:33 +0200594 statistics_proxy_->OnPreDecode(kVideoCodecVP8, kQp);
asapersson6966bd52017-01-03 00:44:06 -0800595
596 statistics_proxy_.reset();
597 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
598}
599
600TEST_F(ReceiveStatisticsProxyTest, Vp8QpHistogramIsNotUpdatedIfNoQpValue) {
asapersson6966bd52017-01-03 00:44:06 -0800601 for (int i = 0; i < kMinRequiredSamples; ++i)
Niels Möller147013a2018-10-01 15:56:33 +0200602 statistics_proxy_->OnPreDecode(kVideoCodecVP8, -1);
asapersson6966bd52017-01-03 00:44:06 -0800603
604 statistics_proxy_.reset();
605 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
606}
607
asaperssonb99baf82017-04-20 04:05:43 -0700608TEST_F(ReceiveStatisticsProxyTest,
609 KeyFrameHistogramNotUpdatedForTooFewSamples) {
610 const bool kIsKeyFrame = false;
611 const int kFrameSizeBytes = 1000;
612
613 for (int i = 0; i < kMinRequiredSamples - 1; ++i)
ilnik6d5b4d62017-08-30 03:32:14 -0700614 statistics_proxy_->OnCompleteFrame(kIsKeyFrame, kFrameSizeBytes,
615 VideoContentType::UNSPECIFIED);
asaperssonb99baf82017-04-20 04:05:43 -0700616
617 EXPECT_EQ(0, statistics_proxy_->GetStats().frame_counts.key_frames);
618 EXPECT_EQ(kMinRequiredSamples - 1,
619 statistics_proxy_->GetStats().frame_counts.delta_frames);
620
621 statistics_proxy_.reset();
622 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
623}
624
625TEST_F(ReceiveStatisticsProxyTest,
626 KeyFrameHistogramUpdatedForMinRequiredSamples) {
627 const bool kIsKeyFrame = false;
628 const int kFrameSizeBytes = 1000;
629
630 for (int i = 0; i < kMinRequiredSamples; ++i)
ilnik6d5b4d62017-08-30 03:32:14 -0700631 statistics_proxy_->OnCompleteFrame(kIsKeyFrame, kFrameSizeBytes,
632 VideoContentType::UNSPECIFIED);
asaperssonb99baf82017-04-20 04:05:43 -0700633
634 EXPECT_EQ(0, statistics_proxy_->GetStats().frame_counts.key_frames);
635 EXPECT_EQ(kMinRequiredSamples,
636 statistics_proxy_->GetStats().frame_counts.delta_frames);
637
638 statistics_proxy_.reset();
639 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
640 EXPECT_EQ(1,
641 metrics::NumEvents("WebRTC.Video.KeyFramesReceivedInPermille", 0));
642}
643
644TEST_F(ReceiveStatisticsProxyTest, KeyFrameHistogramIsUpdated) {
645 const int kFrameSizeBytes = 1000;
646
647 for (int i = 0; i < kMinRequiredSamples; ++i)
ilnik6d5b4d62017-08-30 03:32:14 -0700648 statistics_proxy_->OnCompleteFrame(true, kFrameSizeBytes,
649 VideoContentType::UNSPECIFIED);
asaperssonb99baf82017-04-20 04:05:43 -0700650
651 for (int i = 0; i < kMinRequiredSamples; ++i)
ilnik6d5b4d62017-08-30 03:32:14 -0700652 statistics_proxy_->OnCompleteFrame(false, kFrameSizeBytes,
653 VideoContentType::UNSPECIFIED);
asaperssonb99baf82017-04-20 04:05:43 -0700654
655 EXPECT_EQ(kMinRequiredSamples,
656 statistics_proxy_->GetStats().frame_counts.key_frames);
657 EXPECT_EQ(kMinRequiredSamples,
658 statistics_proxy_->GetStats().frame_counts.delta_frames);
659
660 statistics_proxy_.reset();
661 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
662 EXPECT_EQ(
663 1, metrics::NumEvents("WebRTC.Video.KeyFramesReceivedInPermille", 500));
664}
665
666TEST_F(ReceiveStatisticsProxyTest, TimingHistogramsNotUpdatedForTooFewSamples) {
667 const int kDecodeMs = 1;
668 const int kMaxDecodeMs = 2;
669 const int kCurrentDelayMs = 3;
670 const int kTargetDelayMs = 4;
671 const int kJitterBufferMs = 5;
672 const int kMinPlayoutDelayMs = 6;
673 const int kRenderDelayMs = 7;
674
675 for (int i = 0; i < kMinRequiredSamples - 1; ++i) {
676 statistics_proxy_->OnFrameBufferTimingsUpdated(
677 kDecodeMs, kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs,
678 kJitterBufferMs, kMinPlayoutDelayMs, kRenderDelayMs);
679 }
680
681 statistics_proxy_.reset();
682 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
683 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
684 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
685 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
686 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
687}
688
689TEST_F(ReceiveStatisticsProxyTest, TimingHistogramsAreUpdated) {
690 const int kDecodeMs = 1;
691 const int kMaxDecodeMs = 2;
692 const int kCurrentDelayMs = 3;
693 const int kTargetDelayMs = 4;
694 const int kJitterBufferMs = 5;
695 const int kMinPlayoutDelayMs = 6;
696 const int kRenderDelayMs = 7;
697
698 for (int i = 0; i < kMinRequiredSamples; ++i) {
699 statistics_proxy_->OnFrameBufferTimingsUpdated(
700 kDecodeMs, kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs,
701 kJitterBufferMs, kMinPlayoutDelayMs, kRenderDelayMs);
702 }
703
704 statistics_proxy_.reset();
705 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
706 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
707 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
708 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
709 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
710
711 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DecodeTimeInMs", kDecodeMs));
712 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.JitterBufferDelayInMs",
713 kJitterBufferMs));
714 EXPECT_EQ(1,
715 metrics::NumEvents("WebRTC.Video.TargetDelayInMs", kTargetDelayMs));
716 EXPECT_EQ(
717 1, metrics::NumEvents("WebRTC.Video.CurrentDelayInMs", kCurrentDelayMs));
718 EXPECT_EQ(1,
719 metrics::NumEvents("WebRTC.Video.OnewayDelayInMs", kTargetDelayMs));
720}
721
sprang948b2752017-05-04 02:47:13 -0700722TEST_F(ReceiveStatisticsProxyTest, DoesNotReportStaleFramerates) {
723 const int kDefaultFps = 30;
sprang948b2752017-05-04 02:47:13 -0700724 rtc::scoped_refptr<VideoFrameBuffer> video_frame_buffer(
725 I420Buffer::Create(kWidth, kHeight));
726 VideoFrame frame(video_frame_buffer, kVideoRotation_0, 0);
727
728 for (int i = 0; i < kDefaultFps; ++i) {
729 // Since OnRenderedFrame is never called the fps in each sample will be 0,
730 // i.e. bad
731 frame.set_ntp_time_ms(fake_clock_.CurrentNtpInMilliseconds());
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200732 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
sprang948b2752017-05-04 02:47:13 -0700733 VideoContentType::UNSPECIFIED);
734 statistics_proxy_->OnRenderedFrame(frame);
735 fake_clock_.AdvanceTimeMilliseconds(1000 / kDefaultFps);
736 }
737
738 EXPECT_EQ(kDefaultFps, statistics_proxy_->GetStats().decode_frame_rate);
739 EXPECT_EQ(kDefaultFps, statistics_proxy_->GetStats().render_frame_rate);
740
741 // FPS trackers in stats proxy have a 1000ms sliding window.
742 fake_clock_.AdvanceTimeMilliseconds(1000);
743 EXPECT_EQ(0, statistics_proxy_->GetStats().decode_frame_rate);
744 EXPECT_EQ(0, statistics_proxy_->GetStats().render_frame_rate);
745}
746
asapersson2077f2f2017-05-11 05:37:35 -0700747TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsReceivedFrameStats) {
asapersson2077f2f2017-05-11 05:37:35 -0700748 EXPECT_EQ(0, statistics_proxy_->GetStats().width);
749 EXPECT_EQ(0, statistics_proxy_->GetStats().height);
750 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_rendered);
751
752 statistics_proxy_->OnRenderedFrame(CreateFrame(kWidth, kHeight));
753
754 EXPECT_EQ(kWidth, statistics_proxy_->GetStats().width);
755 EXPECT_EQ(kHeight, statistics_proxy_->GetStats().height);
756 EXPECT_EQ(1u, statistics_proxy_->GetStats().frames_rendered);
757}
758
759TEST_F(ReceiveStatisticsProxyTest,
760 ReceivedFrameHistogramsAreNotUpdatedForTooFewSamples) {
asapersson2077f2f2017-05-11 05:37:35 -0700761 for (int i = 0; i < kMinRequiredSamples - 1; ++i)
762 statistics_proxy_->OnRenderedFrame(CreateFrame(kWidth, kHeight));
763
764 statistics_proxy_.reset();
765 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
766 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
767 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
768 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
769}
770
771TEST_F(ReceiveStatisticsProxyTest, ReceivedFrameHistogramsAreUpdated) {
asapersson2077f2f2017-05-11 05:37:35 -0700772 for (int i = 0; i < kMinRequiredSamples; ++i)
773 statistics_proxy_->OnRenderedFrame(CreateFrame(kWidth, kHeight));
774
775 statistics_proxy_.reset();
776 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
777 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
778 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
779 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
780 EXPECT_EQ(1,
781 metrics::NumEvents("WebRTC.Video.ReceivedWidthInPixels", kWidth));
782 EXPECT_EQ(1,
783 metrics::NumEvents("WebRTC.Video.ReceivedHeightInPixels", kHeight));
784}
785
Åsa Persson81327d52018-06-05 13:34:33 +0200786TEST_F(ReceiveStatisticsProxyTest, ZeroDelayReportedIfFrameNotDelayed) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200787 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Åsa Persson81327d52018-06-05 13:34:33 +0200788 VideoContentType::UNSPECIFIED);
789
790 // Frame not delayed, delayed frames to render: 0%.
791 const int64_t kNowMs = fake_clock_.TimeInMilliseconds();
792 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs));
793
794 // Min run time has passed.
795 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000));
796 statistics_proxy_.reset();
797 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
798 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer", 0));
799 EXPECT_EQ(0, metrics::NumSamples(
800 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
801}
802
803TEST_F(ReceiveStatisticsProxyTest,
804 DelayedFrameHistogramsAreNotUpdatedIfMinRuntimeHasNotPassed) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200805 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Åsa Persson81327d52018-06-05 13:34:33 +0200806 VideoContentType::UNSPECIFIED);
807
808 // Frame not delayed, delayed frames to render: 0%.
809 const int64_t kNowMs = fake_clock_.TimeInMilliseconds();
810 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs));
811
812 // Min run time has not passed.
813 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000) -
814 1);
815 statistics_proxy_.reset();
816 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
817 EXPECT_EQ(0, metrics::NumSamples(
818 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
819}
820
821TEST_F(ReceiveStatisticsProxyTest,
822 DelayedFramesHistogramsAreNotUpdatedIfNoRenderedFrames) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200823 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Åsa Persson81327d52018-06-05 13:34:33 +0200824 VideoContentType::UNSPECIFIED);
825
826 // Min run time has passed. No rendered frames.
827 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000));
828 statistics_proxy_.reset();
829 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
830 EXPECT_EQ(0, metrics::NumSamples(
831 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
832}
833
834TEST_F(ReceiveStatisticsProxyTest, DelayReportedIfFrameIsDelayed) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200835 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Åsa Persson81327d52018-06-05 13:34:33 +0200836 VideoContentType::UNSPECIFIED);
837
838 // Frame delayed 1 ms, delayed frames to render: 100%.
839 const int64_t kNowMs = fake_clock_.TimeInMilliseconds();
840 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs - 1));
841
842 // Min run time has passed.
843 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000));
844 statistics_proxy_.reset();
845 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
846 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer", 100));
847 EXPECT_EQ(1, metrics::NumSamples(
848 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
849 EXPECT_EQ(1, metrics::NumEvents(
850 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs", 1));
851}
852
853TEST_F(ReceiveStatisticsProxyTest, AverageDelayOfDelayedFramesIsReported) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200854 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Åsa Persson81327d52018-06-05 13:34:33 +0200855 VideoContentType::UNSPECIFIED);
856
857 // Two frames delayed (6 ms, 10 ms), delayed frames to render: 50%.
858 const int64_t kNowMs = fake_clock_.TimeInMilliseconds();
859 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs - 10));
860 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs - 6));
861 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs));
862 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs + 1));
863
864 // Min run time has passed.
865 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000));
866 statistics_proxy_.reset();
867 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
868 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer", 50));
869 EXPECT_EQ(1, metrics::NumSamples(
870 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
871 EXPECT_EQ(1, metrics::NumEvents(
872 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs", 8));
873}
874
asapersson2077f2f2017-05-11 05:37:35 -0700875TEST_F(ReceiveStatisticsProxyTest,
876 RtcpHistogramsNotUpdatedIfMinRuntimeHasNotPassed) {
877 InsertFirstRtpPacket(kRemoteSsrc);
878 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000) -
879 1);
880
881 RtcpPacketTypeCounter counter;
882 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc, counter);
883
884 statistics_proxy_.reset();
885 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
886 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
887 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
888}
889
890TEST_F(ReceiveStatisticsProxyTest, RtcpHistogramsAreUpdated) {
891 InsertFirstRtpPacket(kRemoteSsrc);
892 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
893
894 const uint32_t kFirPackets = 100;
895 const uint32_t kPliPackets = 200;
896 const uint32_t kNackPackets = 300;
897
898 RtcpPacketTypeCounter counter;
899 counter.fir_packets = kFirPackets;
900 counter.pli_packets = kPliPackets;
901 counter.nack_packets = kNackPackets;
902 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc, counter);
903
904 statistics_proxy_.reset();
905 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
906 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
907 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
908 EXPECT_EQ(
909 1, metrics::NumEvents("WebRTC.Video.FirPacketsSentPerMinute",
910 kFirPackets * 60 / metrics::kMinRunTimeInSeconds));
911 EXPECT_EQ(
912 1, metrics::NumEvents("WebRTC.Video.PliPacketsSentPerMinute",
913 kPliPackets * 60 / metrics::kMinRunTimeInSeconds));
914 EXPECT_EQ(
915 1, metrics::NumEvents("WebRTC.Video.NackPacketsSentPerMinute",
916 kNackPackets * 60 / metrics::kMinRunTimeInSeconds));
917}
918
sprang892dab52017-08-15 05:00:33 -0700919INSTANTIATE_TEST_CASE_P(ContentTypes,
920 ReceiveStatisticsProxyTest,
921 ::testing::Values(VideoContentType::UNSPECIFIED,
922 VideoContentType::SCREENSHARE));
923
924TEST_P(ReceiveStatisticsProxyTest, InterFrameDelaysAreReported) {
925 const VideoContentType content_type = GetParam();
926 const int kInterFrameDelayMs = 33;
927 for (int i = 0; i < kMinRequiredSamples; ++i) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200928 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200929 content_type);
sprang892dab52017-08-15 05:00:33 -0700930 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
931 }
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +0200932 // One extra with double the interval.
sprang892dab52017-08-15 05:00:33 -0700933 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200934 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200935 content_type);
sprang892dab52017-08-15 05:00:33 -0700936
937 statistics_proxy_.reset();
938 const int kExpectedInterFrame =
939 (kInterFrameDelayMs * (kMinRequiredSamples - 1) +
940 kInterFrameDelayMs * 2) /
941 kMinRequiredSamples;
ilnik6d5b4d62017-08-30 03:32:14 -0700942 if (videocontenttypehelpers::IsScreenshare(content_type)) {
943 EXPECT_EQ(
944 kExpectedInterFrame,
945 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs"));
946 EXPECT_EQ(
947 kInterFrameDelayMs * 2,
948 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
949 } else {
950 EXPECT_EQ(kExpectedInterFrame,
951 metrics::MinSample("WebRTC.Video.InterframeDelayInMs"));
952 EXPECT_EQ(kInterFrameDelayMs * 2,
953 metrics::MinSample("WebRTC.Video.InterframeDelayMaxInMs"));
sprang892dab52017-08-15 05:00:33 -0700954 }
955}
956
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +0200957TEST_P(ReceiveStatisticsProxyTest, InterFrameDelaysPercentilesAreReported) {
958 const VideoContentType content_type = GetParam();
959 const int kInterFrameDelayMs = 33;
960 const int kLastFivePercentsSamples = kMinRequiredSamples * 5 / 100;
961 for (int i = 0; i <= kMinRequiredSamples - kLastFivePercentsSamples; ++i) {
962 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200963 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200964 content_type);
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +0200965 }
966 // Last 5% of intervals are double in size.
967 for (int i = 0; i < kLastFivePercentsSamples; ++i) {
968 fake_clock_.AdvanceTimeMilliseconds(2 * kInterFrameDelayMs);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200969 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200970 content_type);
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +0200971 }
972 // Final sample is outlier and 10 times as big.
973 fake_clock_.AdvanceTimeMilliseconds(10 * kInterFrameDelayMs);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200974 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200975 content_type);
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +0200976
977 statistics_proxy_.reset();
978 const int kExpectedInterFrame = kInterFrameDelayMs * 2;
979 if (videocontenttypehelpers::IsScreenshare(content_type)) {
980 EXPECT_EQ(kExpectedInterFrame,
981 metrics::MinSample(
982 "WebRTC.Video.Screenshare.InterframeDelay95PercentileInMs"));
983 } else {
984 EXPECT_EQ(
985 kExpectedInterFrame,
986 metrics::MinSample("WebRTC.Video.InterframeDelay95PercentileInMs"));
987 }
988}
989
sprang892dab52017-08-15 05:00:33 -0700990TEST_P(ReceiveStatisticsProxyTest, MaxInterFrameDelayOnlyWithValidAverage) {
991 const VideoContentType content_type = GetParam();
992 const int kInterFrameDelayMs = 33;
993 for (int i = 0; i < kMinRequiredSamples; ++i) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200994 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200995 content_type);
sprang892dab52017-08-15 05:00:33 -0700996 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
997 }
998
999 // |kMinRequiredSamples| samples, and thereby intervals, is required. That
1000 // means we're one frame short of having a valid data set.
1001 statistics_proxy_.reset();
1002 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
1003 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
1004 EXPECT_EQ(
1005 0, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1006 EXPECT_EQ(0, metrics::NumSamples(
1007 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1008}
1009
sprang3e86e7e2017-08-22 09:23:28 -07001010TEST_P(ReceiveStatisticsProxyTest, MaxInterFrameDelayOnlyWithPause) {
1011 const VideoContentType content_type = GetParam();
1012 const int kInterFrameDelayMs = 33;
1013 for (int i = 0; i <= kMinRequiredSamples; ++i) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +02001014 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001015 content_type);
sprang3e86e7e2017-08-22 09:23:28 -07001016 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1017 }
1018
1019 // At this state, we should have a valid inter-frame delay.
1020 // Indicate stream paused and make a large jump in time.
1021 statistics_proxy_->OnStreamInactive();
1022 fake_clock_.AdvanceTimeMilliseconds(5000);
1023
1024 // Insert two more frames. The interval during the pause should be disregarded
1025 // in the stats.
Danil Chapovalovb9b146c2018-06-15 12:28:07 +02001026 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001027 content_type);
sprang3e86e7e2017-08-22 09:23:28 -07001028 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +02001029 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001030 content_type);
sprang3e86e7e2017-08-22 09:23:28 -07001031
1032 statistics_proxy_.reset();
ilnik6d5b4d62017-08-30 03:32:14 -07001033 if (videocontenttypehelpers::IsScreenshare(content_type)) {
sprang3e86e7e2017-08-22 09:23:28 -07001034 EXPECT_EQ(
1035 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1036 EXPECT_EQ(1, metrics::NumSamples(
1037 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1038 EXPECT_EQ(
1039 kInterFrameDelayMs,
1040 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1041 EXPECT_EQ(
1042 kInterFrameDelayMs,
1043 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1044 } else {
1045 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
1046 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
1047 EXPECT_EQ(kInterFrameDelayMs,
1048 metrics::MinSample("WebRTC.Video.InterframeDelayInMs"));
1049 EXPECT_EQ(kInterFrameDelayMs,
1050 metrics::MinSample("WebRTC.Video.InterframeDelayMaxInMs"));
1051 }
1052}
1053
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001054TEST_P(ReceiveStatisticsProxyTest, FreezesAreReported) {
1055 const VideoContentType content_type = GetParam();
1056 const int kInterFrameDelayMs = 33;
1057 const int kFreezeDelayMs = 200;
Sergey Silkinbea18ca2018-10-02 16:22:46 +02001058 const int kCallDurationMs =
1059 kMinRequiredSamples * kInterFrameDelayMs + kFreezeDelayMs;
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001060 for (int i = 0; i < kMinRequiredSamples; ++i) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +02001061 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001062 content_type);
1063 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1064 }
1065 // Add extra freeze.
1066 fake_clock_.AdvanceTimeMilliseconds(kFreezeDelayMs);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +02001067 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001068 content_type);
1069
1070 statistics_proxy_.reset();
1071 const int kExpectedTimeBetweenFreezes =
1072 kInterFrameDelayMs * (kMinRequiredSamples - 1);
Sergey Silkinbea18ca2018-10-02 16:22:46 +02001073 const int kExpectedNumberFreezesPerMinute = 60 * 1000 / kCallDurationMs;
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001074 if (videocontenttypehelpers::IsScreenshare(content_type)) {
1075 EXPECT_EQ(
1076 kFreezeDelayMs + kInterFrameDelayMs,
1077 metrics::MinSample("WebRTC.Video.Screenshare.MeanFreezeDurationMs"));
1078 EXPECT_EQ(kExpectedTimeBetweenFreezes,
1079 metrics::MinSample(
1080 "WebRTC.Video.Screenshare.MeanTimeBetweenFreezesMs"));
Sergey Silkinbea18ca2018-10-02 16:22:46 +02001081 EXPECT_EQ(
1082 kExpectedNumberFreezesPerMinute,
1083 metrics::MinSample("WebRTC.Video.Screenshare.NumberFreezesPerMinute"));
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001084 } else {
1085 EXPECT_EQ(kFreezeDelayMs + kInterFrameDelayMs,
1086 metrics::MinSample("WebRTC.Video.MeanFreezeDurationMs"));
1087 EXPECT_EQ(kExpectedTimeBetweenFreezes,
1088 metrics::MinSample("WebRTC.Video.MeanTimeBetweenFreezesMs"));
Sergey Silkinbea18ca2018-10-02 16:22:46 +02001089 EXPECT_EQ(kExpectedNumberFreezesPerMinute,
1090 metrics::MinSample("WebRTC.Video.NumberFreezesPerMinute"));
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001091 }
1092}
1093
1094TEST_P(ReceiveStatisticsProxyTest, PausesAreIgnored) {
1095 const VideoContentType content_type = GetParam();
1096 const int kInterFrameDelayMs = 33;
1097 const int kPauseDurationMs = 10000;
1098 for (int i = 0; i <= kMinRequiredSamples; ++i) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +02001099 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001100 content_type);
1101 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1102 }
1103 // Add a pause.
1104 fake_clock_.AdvanceTimeMilliseconds(kPauseDurationMs);
1105 statistics_proxy_->OnStreamInactive();
1106
1107 // Second playback interval with triple the length.
1108 for (int i = 0; i <= kMinRequiredSamples * 3; ++i) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +02001109 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001110 content_type);
1111 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1112 }
1113
1114 statistics_proxy_.reset();
1115 // Average of two playback intervals.
1116 const int kExpectedTimeBetweenFreezes =
1117 kInterFrameDelayMs * kMinRequiredSamples * 2;
1118 if (videocontenttypehelpers::IsScreenshare(content_type)) {
1119 EXPECT_EQ(-1, metrics::MinSample(
1120 "WebRTC.Video.Screenshare.MeanFreezeDurationMs"));
1121 EXPECT_EQ(kExpectedTimeBetweenFreezes,
1122 metrics::MinSample(
1123 "WebRTC.Video.Screenshare.MeanTimeBetweenFreezesMs"));
1124 } else {
1125 EXPECT_EQ(-1, metrics::MinSample("WebRTC.Video.MeanFreezeDurationMs"));
1126 EXPECT_EQ(kExpectedTimeBetweenFreezes,
1127 metrics::MinSample("WebRTC.Video.MeanTimeBetweenFreezesMs"));
1128 }
1129}
1130
Ilya Nikolaevskiy879f5a32018-05-31 09:47:17 +02001131TEST_P(ReceiveStatisticsProxyTest, ManyPausesAtTheBeginning) {
1132 const VideoContentType content_type = GetParam();
1133 const int kInterFrameDelayMs = 33;
1134 const int kPauseDurationMs = 10000;
1135 for (int i = 0; i <= kMinRequiredSamples; ++i) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +02001136 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy879f5a32018-05-31 09:47:17 +02001137 content_type);
1138 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1139
1140 statistics_proxy_->OnStreamInactive();
1141 fake_clock_.AdvanceTimeMilliseconds(kPauseDurationMs);
1142
Danil Chapovalovb9b146c2018-06-15 12:28:07 +02001143 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
1144 content_type);
Ilya Nikolaevskiy879f5a32018-05-31 09:47:17 +02001145 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1146 }
1147
1148 statistics_proxy_.reset();
1149 // No freezes should be detected, as all long inter-frame delays were pauses.
1150 if (videocontenttypehelpers::IsScreenshare(content_type)) {
1151 EXPECT_EQ(-1, metrics::MinSample(
1152 "WebRTC.Video.Screenshare.MeanFreezeDurationMs"));
1153 } else {
1154 EXPECT_EQ(-1, metrics::MinSample("WebRTC.Video.MeanFreezeDurationMs"));
1155 }
1156}
1157
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001158TEST_P(ReceiveStatisticsProxyTest, TimeInHdReported) {
1159 const VideoContentType content_type = GetParam();
1160 const int kInterFrameDelayMs = 20;
1161 // HD frames.
1162 for (int i = 0; i < kMinRequiredSamples; ++i) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +02001163 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001164 content_type);
1165 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1166 }
1167 // SD frames.
1168 for (int i = 0; i < 2 * kMinRequiredSamples; ++i) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +02001169 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth / 2, kHeight / 2,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001170 content_type);
1171 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1172 }
1173 // Extra last frame.
Danil Chapovalovb9b146c2018-06-15 12:28:07 +02001174 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth / 2, kHeight / 2,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001175 content_type);
1176 statistics_proxy_.reset();
1177 const int kExpectedTimeInHdPercents = 33;
1178 if (videocontenttypehelpers::IsScreenshare(content_type)) {
1179 EXPECT_EQ(
1180 kExpectedTimeInHdPercents,
1181 metrics::MinSample("WebRTC.Video.Screenshare.TimeInHdPercentage"));
1182 } else {
1183 EXPECT_EQ(kExpectedTimeInHdPercents,
1184 metrics::MinSample("WebRTC.Video.TimeInHdPercentage"));
1185 }
1186}
1187
1188TEST_P(ReceiveStatisticsProxyTest, TimeInBlockyVideoReported) {
1189 const VideoContentType content_type = GetParam();
1190 const int kInterFrameDelayMs = 20;
1191 const int kHighQp = 80;
1192 const int kLowQp = 30;
1193 // High quality frames.
1194 for (int i = 0; i < kMinRequiredSamples; ++i) {
1195 statistics_proxy_->OnDecodedFrame(kLowQp, kWidth, kHeight, content_type);
1196 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1197 }
1198 // Blocky frames.
1199 for (int i = 0; i < 2 * kMinRequiredSamples; ++i) {
1200 statistics_proxy_->OnDecodedFrame(kHighQp, kWidth, kHeight, content_type);
1201 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1202 }
1203 // Extra last frame.
1204 statistics_proxy_->OnDecodedFrame(kHighQp, kWidth, kHeight, content_type);
1205 statistics_proxy_.reset();
1206 const int kExpectedTimeInHdPercents = 66;
1207 if (videocontenttypehelpers::IsScreenshare(content_type)) {
1208 EXPECT_EQ(kExpectedTimeInHdPercents,
1209 metrics::MinSample(
1210 "WebRTC.Video.Screenshare.TimeInBlockyVideoPercentage"));
1211 } else {
1212 EXPECT_EQ(kExpectedTimeInHdPercents,
1213 metrics::MinSample("WebRTC.Video.TimeInBlockyVideoPercentage"));
1214 }
1215}
1216
1217TEST_P(ReceiveStatisticsProxyTest, DownscalesReported) {
1218 const VideoContentType content_type = GetParam();
1219 const int kInterFrameDelayMs = 1000; // To ensure long enough call duration.
1220 const int kLowQp = 30;
1221
1222 statistics_proxy_->OnDecodedFrame(kLowQp, kWidth / 2, kHeight / 2,
1223 content_type);
1224 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1225
1226 // Downscale.
1227 statistics_proxy_->OnDecodedFrame(kLowQp, kWidth, kHeight, content_type);
1228 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1229
1230 statistics_proxy_->OnDecodedFrame(kLowQp, kWidth / 2, kHeight / 2,
1231 content_type);
1232 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1233
1234 statistics_proxy_->OnDecodedFrame(kLowQp, kWidth / 2, kHeight / 2,
1235 content_type);
1236 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1237
1238 // Downscale.
1239 statistics_proxy_->OnDecodedFrame(kLowQp, kWidth / 4, kHeight / 4,
1240 content_type);
1241 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1242
1243 statistics_proxy_.reset();
1244 const int kExpectedDownscales = 30; // 2 per 5 seconds = 30 per minute.
1245 if (videocontenttypehelpers::IsScreenshare(content_type)) {
1246 EXPECT_EQ(
1247 kExpectedDownscales,
1248 metrics::MinSample(
1249 "WebRTC.Video.Screenshare.NumberResolutionDownswitchesPerMinute"));
1250 } else {
1251 EXPECT_EQ(kExpectedDownscales,
1252 metrics::MinSample(
1253 "WebRTC.Video.NumberResolutionDownswitchesPerMinute"));
1254 }
1255}
1256
ilnik6d5b4d62017-08-30 03:32:14 -07001257TEST_P(ReceiveStatisticsProxyTest, StatsAreSlicedOnSimulcastAndExperiment) {
1258 VideoContentType content_type = GetParam();
1259 const uint8_t experiment_id = 1;
1260 videocontenttypehelpers::SetExperimentId(&content_type, experiment_id);
1261 const int kInterFrameDelayMs1 = 30;
1262 const int kInterFrameDelayMs2 = 50;
1263
1264 videocontenttypehelpers::SetSimulcastId(&content_type, 1);
1265 for (int i = 0; i <= kMinRequiredSamples; ++i) {
1266 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs1);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +02001267 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001268 content_type);
ilnik6d5b4d62017-08-30 03:32:14 -07001269 }
1270
1271 videocontenttypehelpers::SetSimulcastId(&content_type, 2);
1272 for (int i = 0; i <= kMinRequiredSamples; ++i) {
1273 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs2);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +02001274 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001275 content_type);
ilnik6d5b4d62017-08-30 03:32:14 -07001276 }
1277 statistics_proxy_.reset();
1278
1279 if (videocontenttypehelpers::IsScreenshare(content_type)) {
1280 EXPECT_EQ(
1281 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1282 EXPECT_EQ(1, metrics::NumSamples(
1283 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1284 EXPECT_EQ(1, metrics::NumSamples(
1285 "WebRTC.Video.Screenshare.InterframeDelayInMs.S0"));
1286 EXPECT_EQ(1, metrics::NumSamples(
1287 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs.S0"));
1288 EXPECT_EQ(1, metrics::NumSamples(
1289 "WebRTC.Video.Screenshare.InterframeDelayInMs.S1"));
1290 EXPECT_EQ(1, metrics::NumSamples(
1291 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs.S1"));
1292 EXPECT_EQ(1,
1293 metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"
1294 ".ExperimentGroup0"));
1295 EXPECT_EQ(
1296 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"
1297 ".ExperimentGroup0"));
1298 EXPECT_EQ(
1299 kInterFrameDelayMs1,
1300 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs.S0"));
1301 EXPECT_EQ(
1302 kInterFrameDelayMs2,
1303 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs.S1"));
1304 EXPECT_EQ(
1305 (kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1306 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1307 EXPECT_EQ(
1308 kInterFrameDelayMs2,
1309 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1310 EXPECT_EQ(
1311 (kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1312 metrics::MinSample(
1313 "WebRTC.Video.Screenshare.InterframeDelayInMs.ExperimentGroup0"));
1314 } else {
1315 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
1316 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
1317 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs.S0"));
1318 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs.S0"));
1319 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs.S1"));
1320 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs.S1"));
1321 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"
1322 ".ExperimentGroup0"));
1323 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"
1324 ".ExperimentGroup0"));
1325 EXPECT_EQ(kInterFrameDelayMs1,
1326 metrics::MinSample("WebRTC.Video.InterframeDelayInMs.S0"));
1327 EXPECT_EQ(kInterFrameDelayMs2,
1328 metrics::MinSample("WebRTC.Video.InterframeDelayInMs.S1"));
1329 EXPECT_EQ((kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1330 metrics::MinSample("WebRTC.Video.InterframeDelayInMs"));
1331 EXPECT_EQ(kInterFrameDelayMs2,
1332 metrics::MinSample("WebRTC.Video.InterframeDelayMaxInMs"));
1333 EXPECT_EQ((kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1334 metrics::MinSample(
1335 "WebRTC.Video.InterframeDelayInMs.ExperimentGroup0"));
1336 }
1337}
sakale5ba44e2016-10-26 07:09:24 -07001338} // namespace webrtc