blob: d6044299399eef5b2927b6184a6d7d9372ef5ebd [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"
22#include "system_wrappers/include/metrics_default.h"
23#include "test/gtest.h"
sakale5ba44e2016-10-26 07:09:24 -070024
25namespace webrtc {
asaperssonde9e5ff2016-11-02 07:14:03 -070026namespace {
27const int64_t kFreqOffsetProcessIntervalInMs = 40000;
asapersson46c4e3c2016-11-03 06:48:19 -070028const uint32_t kLocalSsrc = 123;
29const uint32_t kRemoteSsrc = 456;
30const int kMinRequiredSamples = 200;
asaperssonde9e5ff2016-11-02 07:14:03 -070031} // namespace
sakale5ba44e2016-10-26 07:09:24 -070032
33// TODO(sakal): ReceiveStatisticsProxy is lacking unittesting.
sprang892dab52017-08-15 05:00:33 -070034class ReceiveStatisticsProxyTest
35 : public ::testing::TestWithParam<webrtc::VideoContentType> {
sakale5ba44e2016-10-26 07:09:24 -070036 public:
37 ReceiveStatisticsProxyTest() : fake_clock_(1234), config_(GetTestConfig()) {}
38 virtual ~ReceiveStatisticsProxyTest() {}
39
40 protected:
41 virtual void SetUp() {
asaperssonde9e5ff2016-11-02 07:14:03 -070042 metrics::Reset();
sakale5ba44e2016-10-26 07:09:24 -070043 statistics_proxy_.reset(new ReceiveStatisticsProxy(&config_, &fake_clock_));
44 }
45
46 VideoReceiveStream::Config GetTestConfig() {
47 VideoReceiveStream::Config config(nullptr);
asapersson46c4e3c2016-11-03 06:48:19 -070048 config.rtp.local_ssrc = kLocalSsrc;
49 config.rtp.remote_ssrc = kRemoteSsrc;
sakale5ba44e2016-10-26 07:09:24 -070050 return config;
51 }
52
asapersson2077f2f2017-05-11 05:37:35 -070053 void InsertFirstRtpPacket(uint32_t ssrc) {
54 StreamDataCounters counters;
55 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
56 statistics_proxy_->DataCountersUpdated(counters, ssrc);
57 }
58
59 VideoFrame CreateFrame(int width, int height) {
60 VideoFrame frame(I420Buffer::Create(width, height), 0, 0, kVideoRotation_0);
61 frame.set_ntp_time_ms(fake_clock_.CurrentNtpInMilliseconds());
62 return frame;
63 }
64
sakale5ba44e2016-10-26 07:09:24 -070065 SimulatedClock fake_clock_;
asaperssonde9e5ff2016-11-02 07:14:03 -070066 const VideoReceiveStream::Config config_;
sakale5ba44e2016-10-26 07:09:24 -070067 std::unique_ptr<ReceiveStatisticsProxy> statistics_proxy_;
sakale5ba44e2016-10-26 07:09:24 -070068};
69
70TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameIncreasesFramesDecoded) {
71 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_decoded);
72 for (uint32_t i = 1; i <= 3; ++i) {
Oskar Sundbom8e07c132018-01-08 16:45:42 +010073 statistics_proxy_->OnDecodedFrame(rtc::nullopt,
ilnik00d802b2017-04-11 10:34:31 -070074 VideoContentType::UNSPECIFIED);
sakale5ba44e2016-10-26 07:09:24 -070075 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_decoded);
76 }
77}
78
Åsa Perssonb9b07ea2018-01-24 17:04:07 +010079TEST_F(ReceiveStatisticsProxyTest, DecodedFpsIsReported) {
80 const int kFps = 20;
81 const int kRequiredSamples = metrics::kMinRunTimeInSeconds * kFps;
82 for (int i = 0; i < kRequiredSamples; ++i) {
83 statistics_proxy_->OnDecodedFrame(rtc::Optional<uint8_t>(),
84 VideoContentType::UNSPECIFIED);
85 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
86 }
87 statistics_proxy_.reset();
88 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
89 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DecodedFramesPerSecond", kFps));
90}
91
92TEST_F(ReceiveStatisticsProxyTest, DecodedFpsIsNotReportedForTooFewSamples) {
93 const int kFps = 20;
94 const int kRequiredSamples = metrics::kMinRunTimeInSeconds * kFps;
95 for (int i = 0; i < kRequiredSamples - 1; ++i) {
96 statistics_proxy_->OnDecodedFrame(rtc::Optional<uint8_t>(),
97 VideoContentType::UNSPECIFIED);
98 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
99 }
100 statistics_proxy_.reset();
101 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
102}
103
104TEST_F(ReceiveStatisticsProxyTest, DecodedFpsIsReportedWithQpReset) {
105 const int kFps1 = 10;
106 for (int i = 0; i < metrics::kMinRunTimeInSeconds * kFps1; ++i) {
107 statistics_proxy_->OnDecodedFrame(rtc::Optional<uint8_t>(),
108 VideoContentType::UNSPECIFIED);
109 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps1);
110 }
111 // First QP value received, resets frames decoded.
112 const int kFps2 = 20;
113 for (int i = 0; i < metrics::kMinRunTimeInSeconds * kFps2; ++i) {
114 statistics_proxy_->OnDecodedFrame(rtc::Optional<uint8_t>(1u),
115 VideoContentType::UNSPECIFIED);
116 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps2);
117 }
118 statistics_proxy_.reset();
119 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
120 EXPECT_EQ(1,
121 metrics::NumEvents("WebRTC.Video.DecodedFramesPerSecond", kFps2));
122}
123
sakalcc452e12017-02-09 04:53:45 -0800124TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameWithQpResetsFramesDecoded) {
125 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_decoded);
126 for (uint32_t i = 1; i <= 3; ++i) {
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100127 statistics_proxy_->OnDecodedFrame(rtc::nullopt,
ilnik00d802b2017-04-11 10:34:31 -0700128 VideoContentType::UNSPECIFIED);
sakalcc452e12017-02-09 04:53:45 -0800129 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_decoded);
130 }
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100131 statistics_proxy_->OnDecodedFrame(1u, VideoContentType::UNSPECIFIED);
sakalcc452e12017-02-09 04:53:45 -0800132 EXPECT_EQ(1u, statistics_proxy_->GetStats().frames_decoded);
133}
134
135TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameIncreasesQpSum) {
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100136 EXPECT_EQ(rtc::nullopt, statistics_proxy_->GetStats().qp_sum);
137 statistics_proxy_->OnDecodedFrame(3u, VideoContentType::UNSPECIFIED);
138 EXPECT_EQ(3u, statistics_proxy_->GetStats().qp_sum);
139 statistics_proxy_->OnDecodedFrame(127u, VideoContentType::UNSPECIFIED);
140 EXPECT_EQ(130u, statistics_proxy_->GetStats().qp_sum);
sakalcc452e12017-02-09 04:53:45 -0800141}
142
ilnik2e1b40b2017-09-04 07:57:17 -0700143TEST_F(ReceiveStatisticsProxyTest, ReportsContentType) {
144 const std::string kRealtimeString("realtime");
145 const std::string kScreenshareString("screen");
146 EXPECT_EQ(kRealtimeString, videocontenttypehelpers::ToString(
147 statistics_proxy_->GetStats().content_type));
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100148 statistics_proxy_->OnDecodedFrame(3u, VideoContentType::SCREENSHARE);
ilnik2e1b40b2017-09-04 07:57:17 -0700149 EXPECT_EQ(kScreenshareString, videocontenttypehelpers::ToString(
150 statistics_proxy_->GetStats().content_type));
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100151 statistics_proxy_->OnDecodedFrame(3u, VideoContentType::UNSPECIFIED);
ilnik2e1b40b2017-09-04 07:57:17 -0700152 EXPECT_EQ(kRealtimeString, videocontenttypehelpers::ToString(
153 statistics_proxy_->GetStats().content_type));
154}
155
ilnika79cc282017-08-23 05:24:10 -0700156TEST_F(ReceiveStatisticsProxyTest, ReportsMaxInterframeDelay) {
157 const int64_t kInterframeDelayMs1 = 100;
158 const int64_t kInterframeDelayMs2 = 200;
159 const int64_t kInterframeDelayMs3 = 100;
160 EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100161 statistics_proxy_->OnDecodedFrame(3u, VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700162 EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
ilnikf04afde2017-07-07 01:26:24 -0700163
164 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs1);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100165 statistics_proxy_->OnDecodedFrame(127u, VideoContentType::UNSPECIFIED);
ilnikf04afde2017-07-07 01:26:24 -0700166 EXPECT_EQ(kInterframeDelayMs1,
ilnika79cc282017-08-23 05:24:10 -0700167 statistics_proxy_->GetStats().interframe_delay_max_ms);
ilnikf04afde2017-07-07 01:26:24 -0700168
169 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs2);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100170 statistics_proxy_->OnDecodedFrame(127u, VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700171 EXPECT_EQ(kInterframeDelayMs2,
172 statistics_proxy_->GetStats().interframe_delay_max_ms);
173
174 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs3);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100175 statistics_proxy_->OnDecodedFrame(127u, VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700176 // kInterframeDelayMs3 is smaller than kInterframeDelayMs2.
177 EXPECT_EQ(kInterframeDelayMs2,
178 statistics_proxy_->GetStats().interframe_delay_max_ms);
179}
180
181TEST_F(ReceiveStatisticsProxyTest, ReportInterframeDelayInWindow) {
Ilya Nikolaevskiyb06b3582017-10-16 17:59:12 +0200182 const int64_t kInterframeDelayMs1 = 900;
183 const int64_t kInterframeDelayMs2 = 750;
184 const int64_t kInterframeDelayMs3 = 700;
ilnika79cc282017-08-23 05:24:10 -0700185 EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100186 statistics_proxy_->OnDecodedFrame(3u, VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700187 EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
188
189 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs1);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100190 statistics_proxy_->OnDecodedFrame(127u, VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700191 EXPECT_EQ(kInterframeDelayMs1,
192 statistics_proxy_->GetStats().interframe_delay_max_ms);
193
194 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs2);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100195 statistics_proxy_->OnDecodedFrame(127u, VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700196 // Still first delay is the maximum
197 EXPECT_EQ(kInterframeDelayMs1,
198 statistics_proxy_->GetStats().interframe_delay_max_ms);
199
200 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs3);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100201 statistics_proxy_->OnDecodedFrame(127u, VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700202 // Now the first sample is out of the window, so the second is the maximum.
203 EXPECT_EQ(kInterframeDelayMs2,
204 statistics_proxy_->GetStats().interframe_delay_max_ms);
ilnikf04afde2017-07-07 01:26:24 -0700205}
206
sakalcc452e12017-02-09 04:53:45 -0800207TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameWithoutQpQpSumWontExist) {
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100208 EXPECT_EQ(rtc::nullopt, statistics_proxy_->GetStats().qp_sum);
209 statistics_proxy_->OnDecodedFrame(rtc::nullopt,
ilnik00d802b2017-04-11 10:34:31 -0700210 VideoContentType::UNSPECIFIED);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100211 EXPECT_EQ(rtc::nullopt, statistics_proxy_->GetStats().qp_sum);
sakalcc452e12017-02-09 04:53:45 -0800212}
213
214TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameWithoutQpResetsQpSum) {
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100215 EXPECT_EQ(rtc::nullopt, statistics_proxy_->GetStats().qp_sum);
216 statistics_proxy_->OnDecodedFrame(3u, VideoContentType::UNSPECIFIED);
217 EXPECT_EQ(3u, statistics_proxy_->GetStats().qp_sum);
218 statistics_proxy_->OnDecodedFrame(rtc::nullopt,
ilnik00d802b2017-04-11 10:34:31 -0700219 VideoContentType::UNSPECIFIED);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100220 EXPECT_EQ(rtc::nullopt, statistics_proxy_->GetStats().qp_sum);
sakalcc452e12017-02-09 04:53:45 -0800221}
222
hbos50cfe1f2017-01-23 07:21:55 -0800223TEST_F(ReceiveStatisticsProxyTest, OnRenderedFrameIncreasesFramesRendered) {
224 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_rendered);
ilnik00d802b2017-04-11 10:34:31 -0700225 webrtc::VideoFrame frame(webrtc::I420Buffer::Create(1, 1), 0, 0,
226 webrtc::kVideoRotation_0);
hbos50cfe1f2017-01-23 07:21:55 -0800227 for (uint32_t i = 1; i <= 3; ++i) {
228 statistics_proxy_->OnRenderedFrame(frame);
229 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_rendered);
230 }
231}
232
asapersson46c4e3c2016-11-03 06:48:19 -0700233TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsSsrc) {
234 EXPECT_EQ(kRemoteSsrc, statistics_proxy_->GetStats().ssrc);
235}
236
237TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsIncomingPayloadType) {
238 const int kPayloadType = 111;
239 statistics_proxy_->OnIncomingPayloadType(kPayloadType);
240 EXPECT_EQ(kPayloadType, statistics_proxy_->GetStats().current_payload_type);
241}
242
asapersson6966bd52017-01-03 00:44:06 -0800243TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsDecoderImplementationName) {
244 const char* kName = "decoderName";
245 statistics_proxy_->OnDecoderImplementationName(kName);
246 EXPECT_STREQ(
247 kName, statistics_proxy_->GetStats().decoder_implementation_name.c_str());
248}
249
philipela45102f2017-02-22 05:30:39 -0800250TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsOnCompleteFrame) {
251 const int kFrameSizeBytes = 1000;
ilnik6d5b4d62017-08-30 03:32:14 -0700252 statistics_proxy_->OnCompleteFrame(true, kFrameSizeBytes,
253 VideoContentType::UNSPECIFIED);
philipela45102f2017-02-22 05:30:39 -0800254 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
255 EXPECT_EQ(1, stats.network_frame_rate);
philipela45102f2017-02-22 05:30:39 -0800256 EXPECT_EQ(1, stats.frame_counts.key_frames);
257 EXPECT_EQ(0, stats.frame_counts.delta_frames);
asapersson46c4e3c2016-11-03 06:48:19 -0700258}
259
260TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsDecodeTimingStats) {
261 const int kDecodeMs = 1;
262 const int kMaxDecodeMs = 2;
263 const int kCurrentDelayMs = 3;
264 const int kTargetDelayMs = 4;
265 const int kJitterBufferMs = 5;
266 const int kMinPlayoutDelayMs = 6;
267 const int kRenderDelayMs = 7;
268 const int64_t kRttMs = 8;
philipela45102f2017-02-22 05:30:39 -0800269 statistics_proxy_->OnRttUpdate(kRttMs, 0);
270 statistics_proxy_->OnFrameBufferTimingsUpdated(
asapersson46c4e3c2016-11-03 06:48:19 -0700271 kDecodeMs, kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs, kJitterBufferMs,
philipela45102f2017-02-22 05:30:39 -0800272 kMinPlayoutDelayMs, kRenderDelayMs);
asapersson46c4e3c2016-11-03 06:48:19 -0700273 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
274 EXPECT_EQ(kDecodeMs, stats.decode_ms);
275 EXPECT_EQ(kMaxDecodeMs, stats.max_decode_ms);
276 EXPECT_EQ(kCurrentDelayMs, stats.current_delay_ms);
277 EXPECT_EQ(kTargetDelayMs, stats.target_delay_ms);
278 EXPECT_EQ(kJitterBufferMs, stats.jitter_buffer_ms);
279 EXPECT_EQ(kMinPlayoutDelayMs, stats.min_playout_delay_ms);
280 EXPECT_EQ(kRenderDelayMs, stats.render_delay_ms);
281}
282
asapersson6966bd52017-01-03 00:44:06 -0800283TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsRtcpPacketTypeCounts) {
284 const uint32_t kFirPackets = 33;
285 const uint32_t kPliPackets = 44;
286 const uint32_t kNackPackets = 55;
287 RtcpPacketTypeCounter counter;
288 counter.fir_packets = kFirPackets;
289 counter.pli_packets = kPliPackets;
290 counter.nack_packets = kNackPackets;
291 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc, counter);
292 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
293 EXPECT_EQ(kFirPackets, stats.rtcp_packet_type_counts.fir_packets);
294 EXPECT_EQ(kPliPackets, stats.rtcp_packet_type_counts.pli_packets);
295 EXPECT_EQ(kNackPackets, stats.rtcp_packet_type_counts.nack_packets);
296}
297
298TEST_F(ReceiveStatisticsProxyTest,
299 GetStatsReportsNoRtcpPacketTypeCountsForUnknownSsrc) {
300 RtcpPacketTypeCounter counter;
301 counter.fir_packets = 33;
302 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc + 1, counter);
303 EXPECT_EQ(0u,
304 statistics_proxy_->GetStats().rtcp_packet_type_counts.fir_packets);
305}
306
307TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsFrameCounts) {
308 const int kKeyFrames = 3;
309 const int kDeltaFrames = 22;
310 FrameCounts frame_counts;
311 frame_counts.key_frames = kKeyFrames;
312 frame_counts.delta_frames = kDeltaFrames;
313 statistics_proxy_->OnFrameCountsUpdated(frame_counts);
314 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
315 EXPECT_EQ(kKeyFrames, stats.frame_counts.key_frames);
316 EXPECT_EQ(kDeltaFrames, stats.frame_counts.delta_frames);
317}
318
asapersson46c4e3c2016-11-03 06:48:19 -0700319TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsDiscardedPackets) {
320 const int kDiscardedPackets = 12;
321 statistics_proxy_->OnDiscardedPacketsUpdated(kDiscardedPackets);
322 EXPECT_EQ(kDiscardedPackets, statistics_proxy_->GetStats().discarded_packets);
323}
324
asapersson6966bd52017-01-03 00:44:06 -0800325TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsRtcpStats) {
326 const uint8_t kFracLost = 0;
Harald Alvestrandc7c41912017-12-08 09:59:34 +0100327 const int32_t kCumLost = 1;
asapersson6966bd52017-01-03 00:44:06 -0800328 const uint32_t kExtSeqNum = 10;
329 const uint32_t kJitter = 4;
330
331 RtcpStatistics rtcp_stats;
332 rtcp_stats.fraction_lost = kFracLost;
srte186d9c32017-08-04 05:03:53 -0700333 rtcp_stats.packets_lost = kCumLost;
334 rtcp_stats.extended_highest_sequence_number = kExtSeqNum;
asapersson6966bd52017-01-03 00:44:06 -0800335 rtcp_stats.jitter = kJitter;
336 statistics_proxy_->StatisticsUpdated(rtcp_stats, kRemoteSsrc);
337
338 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
339 EXPECT_EQ(kFracLost, stats.rtcp_stats.fraction_lost);
srte186d9c32017-08-04 05:03:53 -0700340 EXPECT_EQ(kCumLost, stats.rtcp_stats.packets_lost);
341 EXPECT_EQ(kExtSeqNum, stats.rtcp_stats.extended_highest_sequence_number);
asapersson6966bd52017-01-03 00:44:06 -0800342 EXPECT_EQ(kJitter, stats.rtcp_stats.jitter);
343}
344
345TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsCName) {
346 const char* kName = "cName";
347 statistics_proxy_->CNameChanged(kName, kRemoteSsrc);
348 EXPECT_STREQ(kName, statistics_proxy_->GetStats().c_name.c_str());
349}
350
351TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsNoCNameForUnknownSsrc) {
352 const char* kName = "cName";
353 statistics_proxy_->CNameChanged(kName, kRemoteSsrc + 1);
354 EXPECT_STREQ("", statistics_proxy_->GetStats().c_name.c_str());
355}
356
ilnik2edc6842017-07-06 03:06:50 -0700357TEST_F(ReceiveStatisticsProxyTest,
ilnik75204c52017-09-04 03:35:40 -0700358 ReportsLongestTimingFrameInfo) {
ilnik2edc6842017-07-06 03:06:50 -0700359 const int64_t kShortEndToEndDelay = 10;
360 const int64_t kMedEndToEndDelay = 20;
361 const int64_t kLongEndToEndDelay = 100;
362 const uint32_t kExpectedRtpTimestamp = 2;
363 TimingFrameInfo info;
364 rtc::Optional<TimingFrameInfo> result;
365 info.rtp_timestamp = kExpectedRtpTimestamp - 1;
366 info.capture_time_ms = 0;
367 info.decode_finish_ms = kShortEndToEndDelay;
368 statistics_proxy_->OnTimingFrameInfoUpdated(info);
369 info.rtp_timestamp =
370 kExpectedRtpTimestamp; // this frame should be reported in the end.
371 info.capture_time_ms = 0;
372 info.decode_finish_ms = kLongEndToEndDelay;
373 statistics_proxy_->OnTimingFrameInfoUpdated(info);
374 info.rtp_timestamp = kExpectedRtpTimestamp + 1;
375 info.capture_time_ms = 0;
376 info.decode_finish_ms = kMedEndToEndDelay;
377 statistics_proxy_->OnTimingFrameInfoUpdated(info);
ilnik75204c52017-09-04 03:35:40 -0700378 result = statistics_proxy_->GetStats().timing_frame_info;
ilnik2edc6842017-07-06 03:06:50 -0700379 EXPECT_TRUE(result);
380 EXPECT_EQ(kExpectedRtpTimestamp, result->rtp_timestamp);
381}
382
ilnik75204c52017-09-04 03:35:40 -0700383TEST_F(ReceiveStatisticsProxyTest, RespectsReportingIntervalForTimingFrames) {
384 TimingFrameInfo info;
ilnik2edc6842017-07-06 03:06:50 -0700385 const int64_t kShortEndToEndDelay = 10;
386 const uint32_t kExpectedRtpTimestamp = 2;
ilnik75204c52017-09-04 03:35:40 -0700387 const int64_t kShortDelayMs = 1000;
388 const int64_t kLongDelayMs = 10000;
ilnik2edc6842017-07-06 03:06:50 -0700389 rtc::Optional<TimingFrameInfo> result;
390 info.rtp_timestamp = kExpectedRtpTimestamp;
391 info.capture_time_ms = 0;
392 info.decode_finish_ms = kShortEndToEndDelay;
393 statistics_proxy_->OnTimingFrameInfoUpdated(info);
ilnik75204c52017-09-04 03:35:40 -0700394 fake_clock_.AdvanceTimeMilliseconds(kShortDelayMs);
395 result = statistics_proxy_->GetStats().timing_frame_info;
ilnik2edc6842017-07-06 03:06:50 -0700396 EXPECT_TRUE(result);
397 EXPECT_EQ(kExpectedRtpTimestamp, result->rtp_timestamp);
ilnik75204c52017-09-04 03:35:40 -0700398 fake_clock_.AdvanceTimeMilliseconds(kLongDelayMs);
399 result = statistics_proxy_->GetStats().timing_frame_info;
ilnik2edc6842017-07-06 03:06:50 -0700400 EXPECT_FALSE(result);
401}
402
asapersson46c4e3c2016-11-03 06:48:19 -0700403TEST_F(ReceiveStatisticsProxyTest, LifetimeHistogramIsUpdated) {
404 const int64_t kTimeSec = 3;
405 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
ilnik6d5b4d62017-08-30 03:32:14 -0700406 // Need at least one frame to report stream lifetime.
407 statistics_proxy_->OnCompleteFrame(true, 1000, VideoContentType::UNSPECIFIED);
asapersson46c4e3c2016-11-03 06:48:19 -0700408 // Histograms are updated when the statistics_proxy_ is deleted.
409 statistics_proxy_.reset();
410 EXPECT_EQ(1,
411 metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
412 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.ReceiveStreamLifetimeInSeconds",
413 kTimeSec));
414}
415
ilnik6d5b4d62017-08-30 03:32:14 -0700416TEST_F(ReceiveStatisticsProxyTest,
417 LifetimeHistogramNotReportedForEmptyStreams) {
418 const int64_t kTimeSec = 3;
419 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
420 // No frames received.
421 // Histograms are updated when the statistics_proxy_ is deleted.
422 statistics_proxy_.reset();
423 EXPECT_EQ(0,
424 metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
425}
426
palmkvista40672a2017-01-13 05:58:34 -0800427TEST_F(ReceiveStatisticsProxyTest, BadCallHistogramsAreUpdated) {
428 // Based on the tuning parameters this will produce 7 uncertain states,
429 // then 10 certainly bad states. There has to be 10 certain states before
430 // any histograms are recorded.
431 const int kNumBadSamples = 17;
432
433 StreamDataCounters counters;
434 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
435 statistics_proxy_->DataCountersUpdated(counters, config_.rtp.remote_ssrc);
436
437 for (int i = 0; i < kNumBadSamples; ++i) {
438 // Since OnRenderedFrame is never called the fps in each sample will be 0,
439 // i.e. bad
440 fake_clock_.AdvanceTimeMilliseconds(1000);
441 statistics_proxy_->OnIncomingRate(0, 0);
442 }
443 // Histograms are updated when the statistics_proxy_ is deleted.
444 statistics_proxy_.reset();
445 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BadCall.Any"));
446 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BadCall.Any", 100));
447
448 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BadCall.FrameRate"));
449 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BadCall.FrameRate", 100));
450
451 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.BadCall.FrameRateVariance"));
452
453 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.BadCall.Qp"));
454}
455
asapersson0c43f772016-11-30 01:42:26 -0800456TEST_F(ReceiveStatisticsProxyTest, PacketLossHistogramIsUpdated) {
457 const uint32_t kCumLost1 = 1;
458 const uint32_t kExtSeqNum1 = 10;
459 const uint32_t kCumLost2 = 2;
460 const uint32_t kExtSeqNum2 = 20;
461
462 // One report block received.
463 RtcpStatistics rtcp_stats1;
srte186d9c32017-08-04 05:03:53 -0700464 rtcp_stats1.packets_lost = kCumLost1;
465 rtcp_stats1.extended_highest_sequence_number = kExtSeqNum1;
asapersson0c43f772016-11-30 01:42:26 -0800466 statistics_proxy_->StatisticsUpdated(rtcp_stats1, kRemoteSsrc);
467
468 // Two report blocks received.
469 RtcpStatistics rtcp_stats2;
srte186d9c32017-08-04 05:03:53 -0700470 rtcp_stats2.packets_lost = kCumLost2;
471 rtcp_stats2.extended_highest_sequence_number = kExtSeqNum2;
asapersson0c43f772016-11-30 01:42:26 -0800472 statistics_proxy_->StatisticsUpdated(rtcp_stats2, kRemoteSsrc);
473
474 // Two received report blocks but min run time has not passed.
475 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
476 SetUp(); // Reset stat proxy causes histograms to be updated.
477 EXPECT_EQ(0,
478 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
479
480 // Two report blocks received.
481 statistics_proxy_->StatisticsUpdated(rtcp_stats1, kRemoteSsrc);
482 statistics_proxy_->StatisticsUpdated(rtcp_stats2, kRemoteSsrc);
483
484 // Two received report blocks and min run time has passed.
485 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
486 SetUp();
487 EXPECT_EQ(1,
488 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
489 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.ReceivedPacketsLostInPercent",
490 (kCumLost2 - kCumLost1) * 100 /
491 (kExtSeqNum2 - kExtSeqNum1)));
492}
493
494TEST_F(ReceiveStatisticsProxyTest,
495 PacketLossHistogramIsNotUpdatedIfLessThanTwoReportBlocksAreReceived) {
496 RtcpStatistics rtcp_stats1;
srte186d9c32017-08-04 05:03:53 -0700497 rtcp_stats1.packets_lost = 1;
498 rtcp_stats1.extended_highest_sequence_number = 10;
asapersson0c43f772016-11-30 01:42:26 -0800499
500 // Min run time has passed but no received report block.
501 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
502 SetUp(); // Reset stat proxy causes histograms to be updated.
503 EXPECT_EQ(0,
504 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
505
506 // Min run time has passed but only one received report block.
507 statistics_proxy_->StatisticsUpdated(rtcp_stats1, kRemoteSsrc);
508 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
509 SetUp();
510 EXPECT_EQ(0,
511 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
512}
513
asapersson2077f2f2017-05-11 05:37:35 -0700514TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsAvSyncOffset) {
515 const int64_t kSyncOffsetMs = 22;
516 const double kFreqKhz = 90.0;
517 EXPECT_EQ(std::numeric_limits<int>::max(),
518 statistics_proxy_->GetStats().sync_offset_ms);
519 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
520 EXPECT_EQ(kSyncOffsetMs, statistics_proxy_->GetStats().sync_offset_ms);
521}
522
asapersson46c4e3c2016-11-03 06:48:19 -0700523TEST_F(ReceiveStatisticsProxyTest, AvSyncOffsetHistogramIsUpdated) {
524 const int64_t kSyncOffsetMs = 22;
525 const double kFreqKhz = 90.0;
526 for (int i = 0; i < kMinRequiredSamples; ++i)
527 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
528 // Histograms are updated when the statistics_proxy_ is deleted.
529 statistics_proxy_.reset();
530 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AVSyncOffsetInMs"));
531 EXPECT_EQ(1,
532 metrics::NumEvents("WebRTC.Video.AVSyncOffsetInMs", kSyncOffsetMs));
533}
534
asaperssonde9e5ff2016-11-02 07:14:03 -0700535TEST_F(ReceiveStatisticsProxyTest, RtpToNtpFrequencyOffsetHistogramIsUpdated) {
536 const int64_t kSyncOffsetMs = 22;
537 const double kFreqKhz = 90.0;
538 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
539 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz + 2.2);
540 fake_clock_.AdvanceTimeMilliseconds(kFreqOffsetProcessIntervalInMs);
541 // Process interval passed, max diff: 2.
542 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz + 1.1);
543 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz - 4.2);
544 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz - 0.9);
545 fake_clock_.AdvanceTimeMilliseconds(kFreqOffsetProcessIntervalInMs);
546 // Process interval passed, max diff: 4.
547 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
548 statistics_proxy_.reset();
549 // Average reported: (2 + 4) / 2 = 3.
550 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtpToNtpFreqOffsetInKhz"));
551 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtpToNtpFreqOffsetInKhz", 3));
552}
553
asapersson6966bd52017-01-03 00:44:06 -0800554TEST_F(ReceiveStatisticsProxyTest, Vp8QpHistogramIsUpdated) {
555 const int kQp = 22;
556 EncodedImage encoded_image;
557 encoded_image.qp_ = kQp;
558 CodecSpecificInfo codec_info;
559 codec_info.codecType = kVideoCodecVP8;
560
561 for (int i = 0; i < kMinRequiredSamples; ++i)
562 statistics_proxy_->OnPreDecode(encoded_image, &codec_info);
563
564 statistics_proxy_.reset();
565 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
566 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Decoded.Vp8.Qp", kQp));
567}
568
569TEST_F(ReceiveStatisticsProxyTest, Vp8QpHistogramIsNotUpdatedForTooFewSamples) {
570 EncodedImage encoded_image;
571 encoded_image.qp_ = 22;
572 CodecSpecificInfo codec_info;
573 codec_info.codecType = kVideoCodecVP8;
574
575 for (int i = 0; i < kMinRequiredSamples - 1; ++i)
576 statistics_proxy_->OnPreDecode(encoded_image, &codec_info);
577
578 statistics_proxy_.reset();
579 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
580}
581
582TEST_F(ReceiveStatisticsProxyTest, Vp8QpHistogramIsNotUpdatedIfNoQpValue) {
583 EncodedImage encoded_image;
584 CodecSpecificInfo codec_info;
585 codec_info.codecType = kVideoCodecVP8;
586
587 for (int i = 0; i < kMinRequiredSamples; ++i)
588 statistics_proxy_->OnPreDecode(encoded_image, &codec_info);
589
590 statistics_proxy_.reset();
591 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
592}
593
asaperssonb99baf82017-04-20 04:05:43 -0700594TEST_F(ReceiveStatisticsProxyTest,
595 KeyFrameHistogramNotUpdatedForTooFewSamples) {
596 const bool kIsKeyFrame = false;
597 const int kFrameSizeBytes = 1000;
598
599 for (int i = 0; i < kMinRequiredSamples - 1; ++i)
ilnik6d5b4d62017-08-30 03:32:14 -0700600 statistics_proxy_->OnCompleteFrame(kIsKeyFrame, kFrameSizeBytes,
601 VideoContentType::UNSPECIFIED);
asaperssonb99baf82017-04-20 04:05:43 -0700602
603 EXPECT_EQ(0, statistics_proxy_->GetStats().frame_counts.key_frames);
604 EXPECT_EQ(kMinRequiredSamples - 1,
605 statistics_proxy_->GetStats().frame_counts.delta_frames);
606
607 statistics_proxy_.reset();
608 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
609}
610
611TEST_F(ReceiveStatisticsProxyTest,
612 KeyFrameHistogramUpdatedForMinRequiredSamples) {
613 const bool kIsKeyFrame = false;
614 const int kFrameSizeBytes = 1000;
615
616 for (int i = 0; i < kMinRequiredSamples; ++i)
ilnik6d5b4d62017-08-30 03:32:14 -0700617 statistics_proxy_->OnCompleteFrame(kIsKeyFrame, kFrameSizeBytes,
618 VideoContentType::UNSPECIFIED);
asaperssonb99baf82017-04-20 04:05:43 -0700619
620 EXPECT_EQ(0, statistics_proxy_->GetStats().frame_counts.key_frames);
621 EXPECT_EQ(kMinRequiredSamples,
622 statistics_proxy_->GetStats().frame_counts.delta_frames);
623
624 statistics_proxy_.reset();
625 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
626 EXPECT_EQ(1,
627 metrics::NumEvents("WebRTC.Video.KeyFramesReceivedInPermille", 0));
628}
629
630TEST_F(ReceiveStatisticsProxyTest, KeyFrameHistogramIsUpdated) {
631 const int kFrameSizeBytes = 1000;
632
633 for (int i = 0; i < kMinRequiredSamples; ++i)
ilnik6d5b4d62017-08-30 03:32:14 -0700634 statistics_proxy_->OnCompleteFrame(true, kFrameSizeBytes,
635 VideoContentType::UNSPECIFIED);
asaperssonb99baf82017-04-20 04:05:43 -0700636
637 for (int i = 0; i < kMinRequiredSamples; ++i)
ilnik6d5b4d62017-08-30 03:32:14 -0700638 statistics_proxy_->OnCompleteFrame(false, kFrameSizeBytes,
639 VideoContentType::UNSPECIFIED);
asaperssonb99baf82017-04-20 04:05:43 -0700640
641 EXPECT_EQ(kMinRequiredSamples,
642 statistics_proxy_->GetStats().frame_counts.key_frames);
643 EXPECT_EQ(kMinRequiredSamples,
644 statistics_proxy_->GetStats().frame_counts.delta_frames);
645
646 statistics_proxy_.reset();
647 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
648 EXPECT_EQ(
649 1, metrics::NumEvents("WebRTC.Video.KeyFramesReceivedInPermille", 500));
650}
651
652TEST_F(ReceiveStatisticsProxyTest, TimingHistogramsNotUpdatedForTooFewSamples) {
653 const int kDecodeMs = 1;
654 const int kMaxDecodeMs = 2;
655 const int kCurrentDelayMs = 3;
656 const int kTargetDelayMs = 4;
657 const int kJitterBufferMs = 5;
658 const int kMinPlayoutDelayMs = 6;
659 const int kRenderDelayMs = 7;
660
661 for (int i = 0; i < kMinRequiredSamples - 1; ++i) {
662 statistics_proxy_->OnFrameBufferTimingsUpdated(
663 kDecodeMs, kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs,
664 kJitterBufferMs, kMinPlayoutDelayMs, kRenderDelayMs);
665 }
666
667 statistics_proxy_.reset();
668 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
669 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
670 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
671 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
672 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
673}
674
675TEST_F(ReceiveStatisticsProxyTest, TimingHistogramsAreUpdated) {
676 const int kDecodeMs = 1;
677 const int kMaxDecodeMs = 2;
678 const int kCurrentDelayMs = 3;
679 const int kTargetDelayMs = 4;
680 const int kJitterBufferMs = 5;
681 const int kMinPlayoutDelayMs = 6;
682 const int kRenderDelayMs = 7;
683
684 for (int i = 0; i < kMinRequiredSamples; ++i) {
685 statistics_proxy_->OnFrameBufferTimingsUpdated(
686 kDecodeMs, kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs,
687 kJitterBufferMs, kMinPlayoutDelayMs, kRenderDelayMs);
688 }
689
690 statistics_proxy_.reset();
691 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
692 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
693 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
694 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
695 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
696
697 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DecodeTimeInMs", kDecodeMs));
698 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.JitterBufferDelayInMs",
699 kJitterBufferMs));
700 EXPECT_EQ(1,
701 metrics::NumEvents("WebRTC.Video.TargetDelayInMs", kTargetDelayMs));
702 EXPECT_EQ(
703 1, metrics::NumEvents("WebRTC.Video.CurrentDelayInMs", kCurrentDelayMs));
704 EXPECT_EQ(1,
705 metrics::NumEvents("WebRTC.Video.OnewayDelayInMs", kTargetDelayMs));
706}
707
sprang948b2752017-05-04 02:47:13 -0700708TEST_F(ReceiveStatisticsProxyTest, DoesNotReportStaleFramerates) {
709 const int kDefaultFps = 30;
710 const int kWidth = 320;
711 const int kHeight = 240;
712
713 rtc::scoped_refptr<VideoFrameBuffer> video_frame_buffer(
714 I420Buffer::Create(kWidth, kHeight));
715 VideoFrame frame(video_frame_buffer, kVideoRotation_0, 0);
716
717 for (int i = 0; i < kDefaultFps; ++i) {
718 // Since OnRenderedFrame is never called the fps in each sample will be 0,
719 // i.e. bad
720 frame.set_ntp_time_ms(fake_clock_.CurrentNtpInMilliseconds());
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100721 statistics_proxy_->OnDecodedFrame(rtc::nullopt,
sprang948b2752017-05-04 02:47:13 -0700722 VideoContentType::UNSPECIFIED);
723 statistics_proxy_->OnRenderedFrame(frame);
724 fake_clock_.AdvanceTimeMilliseconds(1000 / kDefaultFps);
725 }
726
727 EXPECT_EQ(kDefaultFps, statistics_proxy_->GetStats().decode_frame_rate);
728 EXPECT_EQ(kDefaultFps, statistics_proxy_->GetStats().render_frame_rate);
729
730 // FPS trackers in stats proxy have a 1000ms sliding window.
731 fake_clock_.AdvanceTimeMilliseconds(1000);
732 EXPECT_EQ(0, statistics_proxy_->GetStats().decode_frame_rate);
733 EXPECT_EQ(0, statistics_proxy_->GetStats().render_frame_rate);
734}
735
asapersson2077f2f2017-05-11 05:37:35 -0700736TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsReceivedFrameStats) {
737 const int kWidth = 160;
738 const int kHeight = 120;
739 EXPECT_EQ(0, statistics_proxy_->GetStats().width);
740 EXPECT_EQ(0, statistics_proxy_->GetStats().height);
741 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_rendered);
742
743 statistics_proxy_->OnRenderedFrame(CreateFrame(kWidth, kHeight));
744
745 EXPECT_EQ(kWidth, statistics_proxy_->GetStats().width);
746 EXPECT_EQ(kHeight, statistics_proxy_->GetStats().height);
747 EXPECT_EQ(1u, statistics_proxy_->GetStats().frames_rendered);
748}
749
750TEST_F(ReceiveStatisticsProxyTest,
751 ReceivedFrameHistogramsAreNotUpdatedForTooFewSamples) {
752 const int kWidth = 160;
753 const int kHeight = 120;
754
755 for (int i = 0; i < kMinRequiredSamples - 1; ++i)
756 statistics_proxy_->OnRenderedFrame(CreateFrame(kWidth, kHeight));
757
758 statistics_proxy_.reset();
759 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
760 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
761 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
762 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
763}
764
765TEST_F(ReceiveStatisticsProxyTest, ReceivedFrameHistogramsAreUpdated) {
766 const int kWidth = 160;
767 const int kHeight = 120;
768
769 for (int i = 0; i < kMinRequiredSamples; ++i)
770 statistics_proxy_->OnRenderedFrame(CreateFrame(kWidth, kHeight));
771
772 statistics_proxy_.reset();
773 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
774 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
775 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
776 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
777 EXPECT_EQ(1,
778 metrics::NumEvents("WebRTC.Video.ReceivedWidthInPixels", kWidth));
779 EXPECT_EQ(1,
780 metrics::NumEvents("WebRTC.Video.ReceivedHeightInPixels", kHeight));
781}
782
783TEST_F(ReceiveStatisticsProxyTest,
784 RtcpHistogramsNotUpdatedIfMinRuntimeHasNotPassed) {
785 InsertFirstRtpPacket(kRemoteSsrc);
786 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000) -
787 1);
788
789 RtcpPacketTypeCounter counter;
790 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc, counter);
791
792 statistics_proxy_.reset();
793 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
794 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
795 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
796}
797
798TEST_F(ReceiveStatisticsProxyTest, RtcpHistogramsAreUpdated) {
799 InsertFirstRtpPacket(kRemoteSsrc);
800 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
801
802 const uint32_t kFirPackets = 100;
803 const uint32_t kPliPackets = 200;
804 const uint32_t kNackPackets = 300;
805
806 RtcpPacketTypeCounter counter;
807 counter.fir_packets = kFirPackets;
808 counter.pli_packets = kPliPackets;
809 counter.nack_packets = kNackPackets;
810 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc, counter);
811
812 statistics_proxy_.reset();
813 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
814 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
815 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
816 EXPECT_EQ(
817 1, metrics::NumEvents("WebRTC.Video.FirPacketsSentPerMinute",
818 kFirPackets * 60 / metrics::kMinRunTimeInSeconds));
819 EXPECT_EQ(
820 1, metrics::NumEvents("WebRTC.Video.PliPacketsSentPerMinute",
821 kPliPackets * 60 / metrics::kMinRunTimeInSeconds));
822 EXPECT_EQ(
823 1, metrics::NumEvents("WebRTC.Video.NackPacketsSentPerMinute",
824 kNackPackets * 60 / metrics::kMinRunTimeInSeconds));
825}
826
sprang892dab52017-08-15 05:00:33 -0700827INSTANTIATE_TEST_CASE_P(ContentTypes,
828 ReceiveStatisticsProxyTest,
829 ::testing::Values(VideoContentType::UNSPECIFIED,
830 VideoContentType::SCREENSHARE));
831
832TEST_P(ReceiveStatisticsProxyTest, InterFrameDelaysAreReported) {
833 const VideoContentType content_type = GetParam();
834 const int kInterFrameDelayMs = 33;
835 for (int i = 0; i < kMinRequiredSamples; ++i) {
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100836 statistics_proxy_->OnDecodedFrame(rtc::nullopt, content_type);
sprang892dab52017-08-15 05:00:33 -0700837 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
838 }
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +0200839 // One extra with double the interval.
sprang892dab52017-08-15 05:00:33 -0700840 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100841 statistics_proxy_->OnDecodedFrame(rtc::nullopt, content_type);
sprang892dab52017-08-15 05:00:33 -0700842
843 statistics_proxy_.reset();
844 const int kExpectedInterFrame =
845 (kInterFrameDelayMs * (kMinRequiredSamples - 1) +
846 kInterFrameDelayMs * 2) /
847 kMinRequiredSamples;
ilnik6d5b4d62017-08-30 03:32:14 -0700848 if (videocontenttypehelpers::IsScreenshare(content_type)) {
849 EXPECT_EQ(
850 kExpectedInterFrame,
851 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs"));
852 EXPECT_EQ(
853 kInterFrameDelayMs * 2,
854 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
855 } else {
856 EXPECT_EQ(kExpectedInterFrame,
857 metrics::MinSample("WebRTC.Video.InterframeDelayInMs"));
858 EXPECT_EQ(kInterFrameDelayMs * 2,
859 metrics::MinSample("WebRTC.Video.InterframeDelayMaxInMs"));
sprang892dab52017-08-15 05:00:33 -0700860 }
861}
862
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +0200863TEST_P(ReceiveStatisticsProxyTest, InterFrameDelaysPercentilesAreReported) {
864 const VideoContentType content_type = GetParam();
865 const int kInterFrameDelayMs = 33;
866 const int kLastFivePercentsSamples = kMinRequiredSamples * 5 / 100;
867 for (int i = 0; i <= kMinRequiredSamples - kLastFivePercentsSamples; ++i) {
868 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100869 statistics_proxy_->OnDecodedFrame(rtc::nullopt, content_type);
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +0200870 }
871 // Last 5% of intervals are double in size.
872 for (int i = 0; i < kLastFivePercentsSamples; ++i) {
873 fake_clock_.AdvanceTimeMilliseconds(2 * kInterFrameDelayMs);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100874 statistics_proxy_->OnDecodedFrame(rtc::nullopt, content_type);
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +0200875 }
876 // Final sample is outlier and 10 times as big.
877 fake_clock_.AdvanceTimeMilliseconds(10 * kInterFrameDelayMs);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100878 statistics_proxy_->OnDecodedFrame(rtc::nullopt, content_type);
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +0200879
880 statistics_proxy_.reset();
881 const int kExpectedInterFrame = kInterFrameDelayMs * 2;
882 if (videocontenttypehelpers::IsScreenshare(content_type)) {
883 EXPECT_EQ(kExpectedInterFrame,
884 metrics::MinSample(
885 "WebRTC.Video.Screenshare.InterframeDelay95PercentileInMs"));
886 } else {
887 EXPECT_EQ(
888 kExpectedInterFrame,
889 metrics::MinSample("WebRTC.Video.InterframeDelay95PercentileInMs"));
890 }
891}
892
sprang892dab52017-08-15 05:00:33 -0700893TEST_P(ReceiveStatisticsProxyTest, MaxInterFrameDelayOnlyWithValidAverage) {
894 const VideoContentType content_type = GetParam();
895 const int kInterFrameDelayMs = 33;
896 for (int i = 0; i < kMinRequiredSamples; ++i) {
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100897 statistics_proxy_->OnDecodedFrame(rtc::nullopt, content_type);
sprang892dab52017-08-15 05:00:33 -0700898 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
899 }
900
901 // |kMinRequiredSamples| samples, and thereby intervals, is required. That
902 // means we're one frame short of having a valid data set.
903 statistics_proxy_.reset();
904 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
905 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
906 EXPECT_EQ(
907 0, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"));
908 EXPECT_EQ(0, metrics::NumSamples(
909 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
910}
911
sprang3e86e7e2017-08-22 09:23:28 -0700912TEST_P(ReceiveStatisticsProxyTest, MaxInterFrameDelayOnlyWithPause) {
913 const VideoContentType content_type = GetParam();
914 const int kInterFrameDelayMs = 33;
915 for (int i = 0; i <= kMinRequiredSamples; ++i) {
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100916 statistics_proxy_->OnDecodedFrame(rtc::nullopt, content_type);
sprang3e86e7e2017-08-22 09:23:28 -0700917 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
918 }
919
920 // At this state, we should have a valid inter-frame delay.
921 // Indicate stream paused and make a large jump in time.
922 statistics_proxy_->OnStreamInactive();
923 fake_clock_.AdvanceTimeMilliseconds(5000);
924
925 // Insert two more frames. The interval during the pause should be disregarded
926 // in the stats.
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100927 statistics_proxy_->OnDecodedFrame(rtc::nullopt, content_type);
sprang3e86e7e2017-08-22 09:23:28 -0700928 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100929 statistics_proxy_->OnDecodedFrame(rtc::nullopt, content_type);
sprang3e86e7e2017-08-22 09:23:28 -0700930
931 statistics_proxy_.reset();
ilnik6d5b4d62017-08-30 03:32:14 -0700932 if (videocontenttypehelpers::IsScreenshare(content_type)) {
sprang3e86e7e2017-08-22 09:23:28 -0700933 EXPECT_EQ(
934 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"));
935 EXPECT_EQ(1, metrics::NumSamples(
936 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
937 EXPECT_EQ(
938 kInterFrameDelayMs,
939 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs"));
940 EXPECT_EQ(
941 kInterFrameDelayMs,
942 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
943 } else {
944 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
945 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
946 EXPECT_EQ(kInterFrameDelayMs,
947 metrics::MinSample("WebRTC.Video.InterframeDelayInMs"));
948 EXPECT_EQ(kInterFrameDelayMs,
949 metrics::MinSample("WebRTC.Video.InterframeDelayMaxInMs"));
950 }
951}
952
ilnik6d5b4d62017-08-30 03:32:14 -0700953TEST_P(ReceiveStatisticsProxyTest, StatsAreSlicedOnSimulcastAndExperiment) {
954 VideoContentType content_type = GetParam();
955 const uint8_t experiment_id = 1;
956 videocontenttypehelpers::SetExperimentId(&content_type, experiment_id);
957 const int kInterFrameDelayMs1 = 30;
958 const int kInterFrameDelayMs2 = 50;
959
960 videocontenttypehelpers::SetSimulcastId(&content_type, 1);
961 for (int i = 0; i <= kMinRequiredSamples; ++i) {
962 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs1);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100963 statistics_proxy_->OnDecodedFrame(rtc::nullopt, content_type);
ilnik6d5b4d62017-08-30 03:32:14 -0700964 }
965
966 videocontenttypehelpers::SetSimulcastId(&content_type, 2);
967 for (int i = 0; i <= kMinRequiredSamples; ++i) {
968 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs2);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100969 statistics_proxy_->OnDecodedFrame(rtc::nullopt, content_type);
ilnik6d5b4d62017-08-30 03:32:14 -0700970 }
971 statistics_proxy_.reset();
972
973 if (videocontenttypehelpers::IsScreenshare(content_type)) {
974 EXPECT_EQ(
975 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"));
976 EXPECT_EQ(1, metrics::NumSamples(
977 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
978 EXPECT_EQ(1, metrics::NumSamples(
979 "WebRTC.Video.Screenshare.InterframeDelayInMs.S0"));
980 EXPECT_EQ(1, metrics::NumSamples(
981 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs.S0"));
982 EXPECT_EQ(1, metrics::NumSamples(
983 "WebRTC.Video.Screenshare.InterframeDelayInMs.S1"));
984 EXPECT_EQ(1, metrics::NumSamples(
985 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs.S1"));
986 EXPECT_EQ(1,
987 metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"
988 ".ExperimentGroup0"));
989 EXPECT_EQ(
990 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"
991 ".ExperimentGroup0"));
992 EXPECT_EQ(
993 kInterFrameDelayMs1,
994 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs.S0"));
995 EXPECT_EQ(
996 kInterFrameDelayMs2,
997 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs.S1"));
998 EXPECT_EQ(
999 (kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1000 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1001 EXPECT_EQ(
1002 kInterFrameDelayMs2,
1003 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1004 EXPECT_EQ(
1005 (kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1006 metrics::MinSample(
1007 "WebRTC.Video.Screenshare.InterframeDelayInMs.ExperimentGroup0"));
1008 } else {
1009 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
1010 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
1011 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs.S0"));
1012 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs.S0"));
1013 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs.S1"));
1014 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs.S1"));
1015 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"
1016 ".ExperimentGroup0"));
1017 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"
1018 ".ExperimentGroup0"));
1019 EXPECT_EQ(kInterFrameDelayMs1,
1020 metrics::MinSample("WebRTC.Video.InterframeDelayInMs.S0"));
1021 EXPECT_EQ(kInterFrameDelayMs2,
1022 metrics::MinSample("WebRTC.Video.InterframeDelayInMs.S1"));
1023 EXPECT_EQ((kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1024 metrics::MinSample("WebRTC.Video.InterframeDelayInMs"));
1025 EXPECT_EQ(kInterFrameDelayMs2,
1026 metrics::MinSample("WebRTC.Video.InterframeDelayMaxInMs"));
1027 EXPECT_EQ((kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1028 metrics::MinSample(
1029 "WebRTC.Video.InterframeDelayInMs.ExperimentGroup0"));
1030 }
1031}
sakale5ba44e2016-10-26 07:09:24 -07001032} // namespace webrtc