blob: c3b9ae752c4f981855be41767aee9aba22761e47 [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;
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +020031const int kWidth = 1280;
32const int kHeight = 720;
33
asaperssonde9e5ff2016-11-02 07:14:03 -070034} // namespace
sakale5ba44e2016-10-26 07:09:24 -070035
36// TODO(sakal): ReceiveStatisticsProxy is lacking unittesting.
sprang892dab52017-08-15 05:00:33 -070037class ReceiveStatisticsProxyTest
38 : public ::testing::TestWithParam<webrtc::VideoContentType> {
sakale5ba44e2016-10-26 07:09:24 -070039 public:
40 ReceiveStatisticsProxyTest() : fake_clock_(1234), config_(GetTestConfig()) {}
41 virtual ~ReceiveStatisticsProxyTest() {}
42
43 protected:
44 virtual void SetUp() {
asaperssonde9e5ff2016-11-02 07:14:03 -070045 metrics::Reset();
sakale5ba44e2016-10-26 07:09:24 -070046 statistics_proxy_.reset(new ReceiveStatisticsProxy(&config_, &fake_clock_));
47 }
48
49 VideoReceiveStream::Config GetTestConfig() {
50 VideoReceiveStream::Config config(nullptr);
asapersson46c4e3c2016-11-03 06:48:19 -070051 config.rtp.local_ssrc = kLocalSsrc;
52 config.rtp.remote_ssrc = kRemoteSsrc;
sakale5ba44e2016-10-26 07:09:24 -070053 return config;
54 }
55
asapersson2077f2f2017-05-11 05:37:35 -070056 void InsertFirstRtpPacket(uint32_t ssrc) {
57 StreamDataCounters counters;
58 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
59 statistics_proxy_->DataCountersUpdated(counters, ssrc);
60 }
61
62 VideoFrame CreateFrame(int width, int height) {
Åsa Persson81327d52018-06-05 13:34:33 +020063 return CreateVideoFrame(width, height, 0);
64 }
65
66 VideoFrame CreateFrameWithRenderTimeMs(int64_t render_time_ms) {
67 return CreateVideoFrame(kWidth, kHeight, render_time_ms);
68 }
69
70 VideoFrame CreateVideoFrame(int width, int height, int64_t render_time_ms) {
71 VideoFrame frame(I420Buffer::Create(width, height), 0, render_time_ms,
72 kVideoRotation_0);
asapersson2077f2f2017-05-11 05:37:35 -070073 frame.set_ntp_time_ms(fake_clock_.CurrentNtpInMilliseconds());
74 return frame;
75 }
76
sakale5ba44e2016-10-26 07:09:24 -070077 SimulatedClock fake_clock_;
asaperssonde9e5ff2016-11-02 07:14:03 -070078 const VideoReceiveStream::Config config_;
sakale5ba44e2016-10-26 07:09:24 -070079 std::unique_ptr<ReceiveStatisticsProxy> statistics_proxy_;
sakale5ba44e2016-10-26 07:09:24 -070080};
81
82TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameIncreasesFramesDecoded) {
83 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_decoded);
84 for (uint32_t i = 1; i <= 3; ++i) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +020085 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
ilnik00d802b2017-04-11 10:34:31 -070086 VideoContentType::UNSPECIFIED);
sakale5ba44e2016-10-26 07:09:24 -070087 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_decoded);
88 }
89}
90
Åsa Perssonb9b07ea2018-01-24 17:04:07 +010091TEST_F(ReceiveStatisticsProxyTest, DecodedFpsIsReported) {
92 const int kFps = 20;
93 const int kRequiredSamples = metrics::kMinRunTimeInSeconds * kFps;
94 for (int i = 0; i < kRequiredSamples; ++i) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +020095 statistics_proxy_->OnDecodedFrame(absl::optional<uint8_t>(), kWidth,
96 kHeight, VideoContentType::UNSPECIFIED);
Åsa Perssonb9b07ea2018-01-24 17:04:07 +010097 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
98 }
99 statistics_proxy_.reset();
100 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
101 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DecodedFramesPerSecond", kFps));
102}
103
104TEST_F(ReceiveStatisticsProxyTest, DecodedFpsIsNotReportedForTooFewSamples) {
105 const int kFps = 20;
106 const int kRequiredSamples = metrics::kMinRunTimeInSeconds * kFps;
107 for (int i = 0; i < kRequiredSamples - 1; ++i) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200108 statistics_proxy_->OnDecodedFrame(absl::optional<uint8_t>(), kWidth,
109 kHeight, VideoContentType::UNSPECIFIED);
Åsa Perssonb9b07ea2018-01-24 17:04:07 +0100110 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
111 }
112 statistics_proxy_.reset();
113 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
114}
115
116TEST_F(ReceiveStatisticsProxyTest, DecodedFpsIsReportedWithQpReset) {
117 const int kFps1 = 10;
118 for (int i = 0; i < metrics::kMinRunTimeInSeconds * kFps1; ++i) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200119 statistics_proxy_->OnDecodedFrame(absl::optional<uint8_t>(), kWidth,
120 kHeight, VideoContentType::UNSPECIFIED);
Åsa Perssonb9b07ea2018-01-24 17:04:07 +0100121 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps1);
122 }
123 // First QP value received, resets frames decoded.
124 const int kFps2 = 20;
125 for (int i = 0; i < metrics::kMinRunTimeInSeconds * kFps2; ++i) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200126 statistics_proxy_->OnDecodedFrame(absl::optional<uint8_t>(1u), kWidth,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200127 kHeight, VideoContentType::UNSPECIFIED);
Åsa Perssonb9b07ea2018-01-24 17:04:07 +0100128 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps2);
129 }
130 statistics_proxy_.reset();
131 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
132 EXPECT_EQ(1,
133 metrics::NumEvents("WebRTC.Video.DecodedFramesPerSecond", kFps2));
134}
135
sakalcc452e12017-02-09 04:53:45 -0800136TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameWithQpResetsFramesDecoded) {
137 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_decoded);
138 for (uint32_t i = 1; i <= 3; ++i) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200139 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
ilnik00d802b2017-04-11 10:34:31 -0700140 VideoContentType::UNSPECIFIED);
sakalcc452e12017-02-09 04:53:45 -0800141 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_decoded);
142 }
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200143 statistics_proxy_->OnDecodedFrame(1u, kWidth, kHeight,
144 VideoContentType::UNSPECIFIED);
sakalcc452e12017-02-09 04:53:45 -0800145 EXPECT_EQ(1u, statistics_proxy_->GetStats().frames_decoded);
146}
147
148TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameIncreasesQpSum) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200149 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200150 statistics_proxy_->OnDecodedFrame(3u, kWidth, kHeight,
151 VideoContentType::UNSPECIFIED);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100152 EXPECT_EQ(3u, statistics_proxy_->GetStats().qp_sum);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200153 statistics_proxy_->OnDecodedFrame(127u, kWidth, kHeight,
154 VideoContentType::UNSPECIFIED);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100155 EXPECT_EQ(130u, statistics_proxy_->GetStats().qp_sum);
sakalcc452e12017-02-09 04:53:45 -0800156}
157
ilnik2e1b40b2017-09-04 07:57:17 -0700158TEST_F(ReceiveStatisticsProxyTest, ReportsContentType) {
159 const std::string kRealtimeString("realtime");
160 const std::string kScreenshareString("screen");
161 EXPECT_EQ(kRealtimeString, videocontenttypehelpers::ToString(
162 statistics_proxy_->GetStats().content_type));
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200163 statistics_proxy_->OnDecodedFrame(3u, kWidth, kHeight,
164 VideoContentType::SCREENSHARE);
ilnik2e1b40b2017-09-04 07:57:17 -0700165 EXPECT_EQ(kScreenshareString, videocontenttypehelpers::ToString(
166 statistics_proxy_->GetStats().content_type));
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200167 statistics_proxy_->OnDecodedFrame(3u, kWidth, kHeight,
168 VideoContentType::UNSPECIFIED);
ilnik2e1b40b2017-09-04 07:57:17 -0700169 EXPECT_EQ(kRealtimeString, videocontenttypehelpers::ToString(
170 statistics_proxy_->GetStats().content_type));
171}
172
ilnika79cc282017-08-23 05:24:10 -0700173TEST_F(ReceiveStatisticsProxyTest, ReportsMaxInterframeDelay) {
174 const int64_t kInterframeDelayMs1 = 100;
175 const int64_t kInterframeDelayMs2 = 200;
176 const int64_t kInterframeDelayMs3 = 100;
177 EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200178 statistics_proxy_->OnDecodedFrame(3u, kWidth, kHeight,
179 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700180 EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
ilnikf04afde2017-07-07 01:26:24 -0700181
182 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs1);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200183 statistics_proxy_->OnDecodedFrame(127u, kWidth, kHeight,
184 VideoContentType::UNSPECIFIED);
ilnikf04afde2017-07-07 01:26:24 -0700185 EXPECT_EQ(kInterframeDelayMs1,
ilnika79cc282017-08-23 05:24:10 -0700186 statistics_proxy_->GetStats().interframe_delay_max_ms);
ilnikf04afde2017-07-07 01:26:24 -0700187
188 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs2);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200189 statistics_proxy_->OnDecodedFrame(127u, kWidth, kHeight,
190 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700191 EXPECT_EQ(kInterframeDelayMs2,
192 statistics_proxy_->GetStats().interframe_delay_max_ms);
193
194 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs3);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200195 statistics_proxy_->OnDecodedFrame(127u, kWidth, kHeight,
196 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700197 // kInterframeDelayMs3 is smaller than kInterframeDelayMs2.
198 EXPECT_EQ(kInterframeDelayMs2,
199 statistics_proxy_->GetStats().interframe_delay_max_ms);
200}
201
202TEST_F(ReceiveStatisticsProxyTest, ReportInterframeDelayInWindow) {
Ilya Nikolaevskiyb06b3582017-10-16 17:59:12 +0200203 const int64_t kInterframeDelayMs1 = 900;
204 const int64_t kInterframeDelayMs2 = 750;
205 const int64_t kInterframeDelayMs3 = 700;
ilnika79cc282017-08-23 05:24:10 -0700206 EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200207 statistics_proxy_->OnDecodedFrame(3u, kWidth, kHeight,
208 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700209 EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
210
211 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs1);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200212 statistics_proxy_->OnDecodedFrame(127u, kWidth, kHeight,
213 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700214 EXPECT_EQ(kInterframeDelayMs1,
215 statistics_proxy_->GetStats().interframe_delay_max_ms);
216
217 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs2);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200218 statistics_proxy_->OnDecodedFrame(127u, kWidth, kHeight,
219 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700220 // Still first delay is the maximum
221 EXPECT_EQ(kInterframeDelayMs1,
222 statistics_proxy_->GetStats().interframe_delay_max_ms);
223
224 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs3);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200225 statistics_proxy_->OnDecodedFrame(127u, kWidth, kHeight,
226 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700227 // Now the first sample is out of the window, so the second is the maximum.
228 EXPECT_EQ(kInterframeDelayMs2,
229 statistics_proxy_->GetStats().interframe_delay_max_ms);
ilnikf04afde2017-07-07 01:26:24 -0700230}
231
sakalcc452e12017-02-09 04:53:45 -0800232TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameWithoutQpQpSumWontExist) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200233 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
234 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
ilnik00d802b2017-04-11 10:34:31 -0700235 VideoContentType::UNSPECIFIED);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200236 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakalcc452e12017-02-09 04:53:45 -0800237}
238
239TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameWithoutQpResetsQpSum) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200240 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200241 statistics_proxy_->OnDecodedFrame(3u, kWidth, kHeight,
242 VideoContentType::UNSPECIFIED);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100243 EXPECT_EQ(3u, statistics_proxy_->GetStats().qp_sum);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200244 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
ilnik00d802b2017-04-11 10:34:31 -0700245 VideoContentType::UNSPECIFIED);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200246 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakalcc452e12017-02-09 04:53:45 -0800247}
248
hbos50cfe1f2017-01-23 07:21:55 -0800249TEST_F(ReceiveStatisticsProxyTest, OnRenderedFrameIncreasesFramesRendered) {
250 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_rendered);
ilnik00d802b2017-04-11 10:34:31 -0700251 webrtc::VideoFrame frame(webrtc::I420Buffer::Create(1, 1), 0, 0,
252 webrtc::kVideoRotation_0);
hbos50cfe1f2017-01-23 07:21:55 -0800253 for (uint32_t i = 1; i <= 3; ++i) {
254 statistics_proxy_->OnRenderedFrame(frame);
255 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_rendered);
256 }
257}
258
asapersson46c4e3c2016-11-03 06:48:19 -0700259TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsSsrc) {
260 EXPECT_EQ(kRemoteSsrc, statistics_proxy_->GetStats().ssrc);
261}
262
263TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsIncomingPayloadType) {
264 const int kPayloadType = 111;
265 statistics_proxy_->OnIncomingPayloadType(kPayloadType);
266 EXPECT_EQ(kPayloadType, statistics_proxy_->GetStats().current_payload_type);
267}
268
asapersson6966bd52017-01-03 00:44:06 -0800269TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsDecoderImplementationName) {
270 const char* kName = "decoderName";
271 statistics_proxy_->OnDecoderImplementationName(kName);
272 EXPECT_STREQ(
273 kName, statistics_proxy_->GetStats().decoder_implementation_name.c_str());
274}
275
philipela45102f2017-02-22 05:30:39 -0800276TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsOnCompleteFrame) {
277 const int kFrameSizeBytes = 1000;
ilnik6d5b4d62017-08-30 03:32:14 -0700278 statistics_proxy_->OnCompleteFrame(true, kFrameSizeBytes,
279 VideoContentType::UNSPECIFIED);
philipela45102f2017-02-22 05:30:39 -0800280 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
281 EXPECT_EQ(1, stats.network_frame_rate);
philipela45102f2017-02-22 05:30:39 -0800282 EXPECT_EQ(1, stats.frame_counts.key_frames);
283 EXPECT_EQ(0, stats.frame_counts.delta_frames);
asapersson46c4e3c2016-11-03 06:48:19 -0700284}
285
286TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsDecodeTimingStats) {
287 const int kDecodeMs = 1;
288 const int kMaxDecodeMs = 2;
289 const int kCurrentDelayMs = 3;
290 const int kTargetDelayMs = 4;
291 const int kJitterBufferMs = 5;
292 const int kMinPlayoutDelayMs = 6;
293 const int kRenderDelayMs = 7;
294 const int64_t kRttMs = 8;
philipela45102f2017-02-22 05:30:39 -0800295 statistics_proxy_->OnRttUpdate(kRttMs, 0);
296 statistics_proxy_->OnFrameBufferTimingsUpdated(
asapersson46c4e3c2016-11-03 06:48:19 -0700297 kDecodeMs, kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs, kJitterBufferMs,
philipela45102f2017-02-22 05:30:39 -0800298 kMinPlayoutDelayMs, kRenderDelayMs);
asapersson46c4e3c2016-11-03 06:48:19 -0700299 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
300 EXPECT_EQ(kDecodeMs, stats.decode_ms);
301 EXPECT_EQ(kMaxDecodeMs, stats.max_decode_ms);
302 EXPECT_EQ(kCurrentDelayMs, stats.current_delay_ms);
303 EXPECT_EQ(kTargetDelayMs, stats.target_delay_ms);
304 EXPECT_EQ(kJitterBufferMs, stats.jitter_buffer_ms);
305 EXPECT_EQ(kMinPlayoutDelayMs, stats.min_playout_delay_ms);
306 EXPECT_EQ(kRenderDelayMs, stats.render_delay_ms);
307}
308
asapersson6966bd52017-01-03 00:44:06 -0800309TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsRtcpPacketTypeCounts) {
310 const uint32_t kFirPackets = 33;
311 const uint32_t kPliPackets = 44;
312 const uint32_t kNackPackets = 55;
313 RtcpPacketTypeCounter counter;
314 counter.fir_packets = kFirPackets;
315 counter.pli_packets = kPliPackets;
316 counter.nack_packets = kNackPackets;
317 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc, counter);
318 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
319 EXPECT_EQ(kFirPackets, stats.rtcp_packet_type_counts.fir_packets);
320 EXPECT_EQ(kPliPackets, stats.rtcp_packet_type_counts.pli_packets);
321 EXPECT_EQ(kNackPackets, stats.rtcp_packet_type_counts.nack_packets);
322}
323
324TEST_F(ReceiveStatisticsProxyTest,
325 GetStatsReportsNoRtcpPacketTypeCountsForUnknownSsrc) {
326 RtcpPacketTypeCounter counter;
327 counter.fir_packets = 33;
328 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc + 1, counter);
329 EXPECT_EQ(0u,
330 statistics_proxy_->GetStats().rtcp_packet_type_counts.fir_packets);
331}
332
333TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsFrameCounts) {
334 const int kKeyFrames = 3;
335 const int kDeltaFrames = 22;
336 FrameCounts frame_counts;
337 frame_counts.key_frames = kKeyFrames;
338 frame_counts.delta_frames = kDeltaFrames;
339 statistics_proxy_->OnFrameCountsUpdated(frame_counts);
340 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
341 EXPECT_EQ(kKeyFrames, stats.frame_counts.key_frames);
342 EXPECT_EQ(kDeltaFrames, stats.frame_counts.delta_frames);
343}
344
asapersson46c4e3c2016-11-03 06:48:19 -0700345TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsDiscardedPackets) {
346 const int kDiscardedPackets = 12;
347 statistics_proxy_->OnDiscardedPacketsUpdated(kDiscardedPackets);
348 EXPECT_EQ(kDiscardedPackets, statistics_proxy_->GetStats().discarded_packets);
349}
350
asapersson6966bd52017-01-03 00:44:06 -0800351TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsRtcpStats) {
352 const uint8_t kFracLost = 0;
Harald Alvestrandc7c41912017-12-08 09:59:34 +0100353 const int32_t kCumLost = 1;
asapersson6966bd52017-01-03 00:44:06 -0800354 const uint32_t kExtSeqNum = 10;
355 const uint32_t kJitter = 4;
356
357 RtcpStatistics rtcp_stats;
358 rtcp_stats.fraction_lost = kFracLost;
srte186d9c32017-08-04 05:03:53 -0700359 rtcp_stats.packets_lost = kCumLost;
360 rtcp_stats.extended_highest_sequence_number = kExtSeqNum;
asapersson6966bd52017-01-03 00:44:06 -0800361 rtcp_stats.jitter = kJitter;
362 statistics_proxy_->StatisticsUpdated(rtcp_stats, kRemoteSsrc);
363
364 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
365 EXPECT_EQ(kFracLost, stats.rtcp_stats.fraction_lost);
srte186d9c32017-08-04 05:03:53 -0700366 EXPECT_EQ(kCumLost, stats.rtcp_stats.packets_lost);
367 EXPECT_EQ(kExtSeqNum, stats.rtcp_stats.extended_highest_sequence_number);
asapersson6966bd52017-01-03 00:44:06 -0800368 EXPECT_EQ(kJitter, stats.rtcp_stats.jitter);
369}
370
371TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsCName) {
372 const char* kName = "cName";
373 statistics_proxy_->CNameChanged(kName, kRemoteSsrc);
374 EXPECT_STREQ(kName, statistics_proxy_->GetStats().c_name.c_str());
375}
376
377TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsNoCNameForUnknownSsrc) {
378 const char* kName = "cName";
379 statistics_proxy_->CNameChanged(kName, kRemoteSsrc + 1);
380 EXPECT_STREQ("", statistics_proxy_->GetStats().c_name.c_str());
381}
382
ilnik2edc6842017-07-06 03:06:50 -0700383TEST_F(ReceiveStatisticsProxyTest,
ilnik75204c52017-09-04 03:35:40 -0700384 ReportsLongestTimingFrameInfo) {
ilnik2edc6842017-07-06 03:06:50 -0700385 const int64_t kShortEndToEndDelay = 10;
386 const int64_t kMedEndToEndDelay = 20;
387 const int64_t kLongEndToEndDelay = 100;
388 const uint32_t kExpectedRtpTimestamp = 2;
389 TimingFrameInfo info;
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200390 absl::optional<TimingFrameInfo> result;
ilnik2edc6842017-07-06 03:06:50 -0700391 info.rtp_timestamp = kExpectedRtpTimestamp - 1;
392 info.capture_time_ms = 0;
393 info.decode_finish_ms = kShortEndToEndDelay;
394 statistics_proxy_->OnTimingFrameInfoUpdated(info);
395 info.rtp_timestamp =
396 kExpectedRtpTimestamp; // this frame should be reported in the end.
397 info.capture_time_ms = 0;
398 info.decode_finish_ms = kLongEndToEndDelay;
399 statistics_proxy_->OnTimingFrameInfoUpdated(info);
400 info.rtp_timestamp = kExpectedRtpTimestamp + 1;
401 info.capture_time_ms = 0;
402 info.decode_finish_ms = kMedEndToEndDelay;
403 statistics_proxy_->OnTimingFrameInfoUpdated(info);
ilnik75204c52017-09-04 03:35:40 -0700404 result = statistics_proxy_->GetStats().timing_frame_info;
ilnik2edc6842017-07-06 03:06:50 -0700405 EXPECT_TRUE(result);
406 EXPECT_EQ(kExpectedRtpTimestamp, result->rtp_timestamp);
407}
408
ilnik75204c52017-09-04 03:35:40 -0700409TEST_F(ReceiveStatisticsProxyTest, RespectsReportingIntervalForTimingFrames) {
410 TimingFrameInfo info;
ilnik2edc6842017-07-06 03:06:50 -0700411 const int64_t kShortEndToEndDelay = 10;
412 const uint32_t kExpectedRtpTimestamp = 2;
ilnik75204c52017-09-04 03:35:40 -0700413 const int64_t kShortDelayMs = 1000;
414 const int64_t kLongDelayMs = 10000;
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200415 absl::optional<TimingFrameInfo> result;
ilnik2edc6842017-07-06 03:06:50 -0700416 info.rtp_timestamp = kExpectedRtpTimestamp;
417 info.capture_time_ms = 0;
418 info.decode_finish_ms = kShortEndToEndDelay;
419 statistics_proxy_->OnTimingFrameInfoUpdated(info);
ilnik75204c52017-09-04 03:35:40 -0700420 fake_clock_.AdvanceTimeMilliseconds(kShortDelayMs);
421 result = statistics_proxy_->GetStats().timing_frame_info;
ilnik2edc6842017-07-06 03:06:50 -0700422 EXPECT_TRUE(result);
423 EXPECT_EQ(kExpectedRtpTimestamp, result->rtp_timestamp);
ilnik75204c52017-09-04 03:35:40 -0700424 fake_clock_.AdvanceTimeMilliseconds(kLongDelayMs);
425 result = statistics_proxy_->GetStats().timing_frame_info;
ilnik2edc6842017-07-06 03:06:50 -0700426 EXPECT_FALSE(result);
427}
428
asapersson46c4e3c2016-11-03 06:48:19 -0700429TEST_F(ReceiveStatisticsProxyTest, LifetimeHistogramIsUpdated) {
430 const int64_t kTimeSec = 3;
431 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
ilnik6d5b4d62017-08-30 03:32:14 -0700432 // Need at least one frame to report stream lifetime.
433 statistics_proxy_->OnCompleteFrame(true, 1000, VideoContentType::UNSPECIFIED);
asapersson46c4e3c2016-11-03 06:48:19 -0700434 // Histograms are updated when the statistics_proxy_ is deleted.
435 statistics_proxy_.reset();
436 EXPECT_EQ(1,
437 metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
438 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.ReceiveStreamLifetimeInSeconds",
439 kTimeSec));
440}
441
ilnik6d5b4d62017-08-30 03:32:14 -0700442TEST_F(ReceiveStatisticsProxyTest,
443 LifetimeHistogramNotReportedForEmptyStreams) {
444 const int64_t kTimeSec = 3;
445 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
446 // No frames received.
447 // Histograms are updated when the statistics_proxy_ is deleted.
448 statistics_proxy_.reset();
449 EXPECT_EQ(0,
450 metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
451}
452
palmkvista40672a2017-01-13 05:58:34 -0800453TEST_F(ReceiveStatisticsProxyTest, BadCallHistogramsAreUpdated) {
454 // Based on the tuning parameters this will produce 7 uncertain states,
455 // then 10 certainly bad states. There has to be 10 certain states before
456 // any histograms are recorded.
457 const int kNumBadSamples = 17;
458
459 StreamDataCounters counters;
460 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
461 statistics_proxy_->DataCountersUpdated(counters, config_.rtp.remote_ssrc);
462
463 for (int i = 0; i < kNumBadSamples; ++i) {
464 // Since OnRenderedFrame is never called the fps in each sample will be 0,
465 // i.e. bad
466 fake_clock_.AdvanceTimeMilliseconds(1000);
467 statistics_proxy_->OnIncomingRate(0, 0);
468 }
469 // Histograms are updated when the statistics_proxy_ is deleted.
470 statistics_proxy_.reset();
471 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BadCall.Any"));
472 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BadCall.Any", 100));
473
474 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BadCall.FrameRate"));
475 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BadCall.FrameRate", 100));
476
477 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.BadCall.FrameRateVariance"));
478
479 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.BadCall.Qp"));
480}
481
asapersson0c43f772016-11-30 01:42:26 -0800482TEST_F(ReceiveStatisticsProxyTest, PacketLossHistogramIsUpdated) {
483 const uint32_t kCumLost1 = 1;
484 const uint32_t kExtSeqNum1 = 10;
485 const uint32_t kCumLost2 = 2;
486 const uint32_t kExtSeqNum2 = 20;
487
488 // One report block received.
489 RtcpStatistics rtcp_stats1;
srte186d9c32017-08-04 05:03:53 -0700490 rtcp_stats1.packets_lost = kCumLost1;
491 rtcp_stats1.extended_highest_sequence_number = kExtSeqNum1;
asapersson0c43f772016-11-30 01:42:26 -0800492 statistics_proxy_->StatisticsUpdated(rtcp_stats1, kRemoteSsrc);
493
494 // Two report blocks received.
495 RtcpStatistics rtcp_stats2;
srte186d9c32017-08-04 05:03:53 -0700496 rtcp_stats2.packets_lost = kCumLost2;
497 rtcp_stats2.extended_highest_sequence_number = kExtSeqNum2;
asapersson0c43f772016-11-30 01:42:26 -0800498 statistics_proxy_->StatisticsUpdated(rtcp_stats2, kRemoteSsrc);
499
500 // Two received report blocks but min run time has not passed.
501 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
502 SetUp(); // Reset stat proxy causes histograms to be updated.
503 EXPECT_EQ(0,
504 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
505
506 // Two report blocks received.
507 statistics_proxy_->StatisticsUpdated(rtcp_stats1, kRemoteSsrc);
508 statistics_proxy_->StatisticsUpdated(rtcp_stats2, kRemoteSsrc);
509
510 // Two received report blocks and min run time has passed.
511 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
512 SetUp();
513 EXPECT_EQ(1,
514 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
515 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.ReceivedPacketsLostInPercent",
516 (kCumLost2 - kCumLost1) * 100 /
517 (kExtSeqNum2 - kExtSeqNum1)));
518}
519
520TEST_F(ReceiveStatisticsProxyTest,
521 PacketLossHistogramIsNotUpdatedIfLessThanTwoReportBlocksAreReceived) {
522 RtcpStatistics rtcp_stats1;
srte186d9c32017-08-04 05:03:53 -0700523 rtcp_stats1.packets_lost = 1;
524 rtcp_stats1.extended_highest_sequence_number = 10;
asapersson0c43f772016-11-30 01:42:26 -0800525
526 // Min run time has passed but no received report block.
527 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
528 SetUp(); // Reset stat proxy causes histograms to be updated.
529 EXPECT_EQ(0,
530 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
531
532 // Min run time has passed but only one received report block.
533 statistics_proxy_->StatisticsUpdated(rtcp_stats1, kRemoteSsrc);
534 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
535 SetUp();
536 EXPECT_EQ(0,
537 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
538}
539
asapersson2077f2f2017-05-11 05:37:35 -0700540TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsAvSyncOffset) {
541 const int64_t kSyncOffsetMs = 22;
542 const double kFreqKhz = 90.0;
543 EXPECT_EQ(std::numeric_limits<int>::max(),
544 statistics_proxy_->GetStats().sync_offset_ms);
545 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
546 EXPECT_EQ(kSyncOffsetMs, statistics_proxy_->GetStats().sync_offset_ms);
547}
548
asapersson46c4e3c2016-11-03 06:48:19 -0700549TEST_F(ReceiveStatisticsProxyTest, AvSyncOffsetHistogramIsUpdated) {
550 const int64_t kSyncOffsetMs = 22;
551 const double kFreqKhz = 90.0;
552 for (int i = 0; i < kMinRequiredSamples; ++i)
553 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
554 // Histograms are updated when the statistics_proxy_ is deleted.
555 statistics_proxy_.reset();
556 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AVSyncOffsetInMs"));
557 EXPECT_EQ(1,
558 metrics::NumEvents("WebRTC.Video.AVSyncOffsetInMs", kSyncOffsetMs));
559}
560
asaperssonde9e5ff2016-11-02 07:14:03 -0700561TEST_F(ReceiveStatisticsProxyTest, RtpToNtpFrequencyOffsetHistogramIsUpdated) {
562 const int64_t kSyncOffsetMs = 22;
563 const double kFreqKhz = 90.0;
564 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
565 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz + 2.2);
566 fake_clock_.AdvanceTimeMilliseconds(kFreqOffsetProcessIntervalInMs);
567 // Process interval passed, max diff: 2.
568 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz + 1.1);
569 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz - 4.2);
570 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz - 0.9);
571 fake_clock_.AdvanceTimeMilliseconds(kFreqOffsetProcessIntervalInMs);
572 // Process interval passed, max diff: 4.
573 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
574 statistics_proxy_.reset();
575 // Average reported: (2 + 4) / 2 = 3.
576 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtpToNtpFreqOffsetInKhz"));
577 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtpToNtpFreqOffsetInKhz", 3));
578}
579
asapersson6966bd52017-01-03 00:44:06 -0800580TEST_F(ReceiveStatisticsProxyTest, Vp8QpHistogramIsUpdated) {
581 const int kQp = 22;
582 EncodedImage encoded_image;
583 encoded_image.qp_ = kQp;
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(1, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
592 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Decoded.Vp8.Qp", kQp));
593}
594
595TEST_F(ReceiveStatisticsProxyTest, Vp8QpHistogramIsNotUpdatedForTooFewSamples) {
596 EncodedImage encoded_image;
597 encoded_image.qp_ = 22;
598 CodecSpecificInfo codec_info;
599 codec_info.codecType = kVideoCodecVP8;
600
601 for (int i = 0; i < kMinRequiredSamples - 1; ++i)
602 statistics_proxy_->OnPreDecode(encoded_image, &codec_info);
603
604 statistics_proxy_.reset();
605 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
606}
607
608TEST_F(ReceiveStatisticsProxyTest, Vp8QpHistogramIsNotUpdatedIfNoQpValue) {
609 EncodedImage encoded_image;
610 CodecSpecificInfo codec_info;
611 codec_info.codecType = kVideoCodecVP8;
612
613 for (int i = 0; i < kMinRequiredSamples; ++i)
614 statistics_proxy_->OnPreDecode(encoded_image, &codec_info);
615
616 statistics_proxy_.reset();
617 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
618}
619
asaperssonb99baf82017-04-20 04:05:43 -0700620TEST_F(ReceiveStatisticsProxyTest,
621 KeyFrameHistogramNotUpdatedForTooFewSamples) {
622 const bool kIsKeyFrame = false;
623 const int kFrameSizeBytes = 1000;
624
625 for (int i = 0; i < kMinRequiredSamples - 1; ++i)
ilnik6d5b4d62017-08-30 03:32:14 -0700626 statistics_proxy_->OnCompleteFrame(kIsKeyFrame, kFrameSizeBytes,
627 VideoContentType::UNSPECIFIED);
asaperssonb99baf82017-04-20 04:05:43 -0700628
629 EXPECT_EQ(0, statistics_proxy_->GetStats().frame_counts.key_frames);
630 EXPECT_EQ(kMinRequiredSamples - 1,
631 statistics_proxy_->GetStats().frame_counts.delta_frames);
632
633 statistics_proxy_.reset();
634 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
635}
636
637TEST_F(ReceiveStatisticsProxyTest,
638 KeyFrameHistogramUpdatedForMinRequiredSamples) {
639 const bool kIsKeyFrame = false;
640 const int kFrameSizeBytes = 1000;
641
642 for (int i = 0; i < kMinRequiredSamples; ++i)
ilnik6d5b4d62017-08-30 03:32:14 -0700643 statistics_proxy_->OnCompleteFrame(kIsKeyFrame, kFrameSizeBytes,
644 VideoContentType::UNSPECIFIED);
asaperssonb99baf82017-04-20 04:05:43 -0700645
646 EXPECT_EQ(0, statistics_proxy_->GetStats().frame_counts.key_frames);
647 EXPECT_EQ(kMinRequiredSamples,
648 statistics_proxy_->GetStats().frame_counts.delta_frames);
649
650 statistics_proxy_.reset();
651 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
652 EXPECT_EQ(1,
653 metrics::NumEvents("WebRTC.Video.KeyFramesReceivedInPermille", 0));
654}
655
656TEST_F(ReceiveStatisticsProxyTest, KeyFrameHistogramIsUpdated) {
657 const int kFrameSizeBytes = 1000;
658
659 for (int i = 0; i < kMinRequiredSamples; ++i)
ilnik6d5b4d62017-08-30 03:32:14 -0700660 statistics_proxy_->OnCompleteFrame(true, kFrameSizeBytes,
661 VideoContentType::UNSPECIFIED);
asaperssonb99baf82017-04-20 04:05:43 -0700662
663 for (int i = 0; i < kMinRequiredSamples; ++i)
ilnik6d5b4d62017-08-30 03:32:14 -0700664 statistics_proxy_->OnCompleteFrame(false, kFrameSizeBytes,
665 VideoContentType::UNSPECIFIED);
asaperssonb99baf82017-04-20 04:05:43 -0700666
667 EXPECT_EQ(kMinRequiredSamples,
668 statistics_proxy_->GetStats().frame_counts.key_frames);
669 EXPECT_EQ(kMinRequiredSamples,
670 statistics_proxy_->GetStats().frame_counts.delta_frames);
671
672 statistics_proxy_.reset();
673 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
674 EXPECT_EQ(
675 1, metrics::NumEvents("WebRTC.Video.KeyFramesReceivedInPermille", 500));
676}
677
678TEST_F(ReceiveStatisticsProxyTest, TimingHistogramsNotUpdatedForTooFewSamples) {
679 const int kDecodeMs = 1;
680 const int kMaxDecodeMs = 2;
681 const int kCurrentDelayMs = 3;
682 const int kTargetDelayMs = 4;
683 const int kJitterBufferMs = 5;
684 const int kMinPlayoutDelayMs = 6;
685 const int kRenderDelayMs = 7;
686
687 for (int i = 0; i < kMinRequiredSamples - 1; ++i) {
688 statistics_proxy_->OnFrameBufferTimingsUpdated(
689 kDecodeMs, kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs,
690 kJitterBufferMs, kMinPlayoutDelayMs, kRenderDelayMs);
691 }
692
693 statistics_proxy_.reset();
694 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
695 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
696 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
697 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
698 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
699}
700
701TEST_F(ReceiveStatisticsProxyTest, TimingHistogramsAreUpdated) {
702 const int kDecodeMs = 1;
703 const int kMaxDecodeMs = 2;
704 const int kCurrentDelayMs = 3;
705 const int kTargetDelayMs = 4;
706 const int kJitterBufferMs = 5;
707 const int kMinPlayoutDelayMs = 6;
708 const int kRenderDelayMs = 7;
709
710 for (int i = 0; i < kMinRequiredSamples; ++i) {
711 statistics_proxy_->OnFrameBufferTimingsUpdated(
712 kDecodeMs, kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs,
713 kJitterBufferMs, kMinPlayoutDelayMs, kRenderDelayMs);
714 }
715
716 statistics_proxy_.reset();
717 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
718 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
719 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
720 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
721 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
722
723 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DecodeTimeInMs", kDecodeMs));
724 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.JitterBufferDelayInMs",
725 kJitterBufferMs));
726 EXPECT_EQ(1,
727 metrics::NumEvents("WebRTC.Video.TargetDelayInMs", kTargetDelayMs));
728 EXPECT_EQ(
729 1, metrics::NumEvents("WebRTC.Video.CurrentDelayInMs", kCurrentDelayMs));
730 EXPECT_EQ(1,
731 metrics::NumEvents("WebRTC.Video.OnewayDelayInMs", kTargetDelayMs));
732}
733
sprang948b2752017-05-04 02:47:13 -0700734TEST_F(ReceiveStatisticsProxyTest, DoesNotReportStaleFramerates) {
735 const int kDefaultFps = 30;
sprang948b2752017-05-04 02:47:13 -0700736 rtc::scoped_refptr<VideoFrameBuffer> video_frame_buffer(
737 I420Buffer::Create(kWidth, kHeight));
738 VideoFrame frame(video_frame_buffer, kVideoRotation_0, 0);
739
740 for (int i = 0; i < kDefaultFps; ++i) {
741 // Since OnRenderedFrame is never called the fps in each sample will be 0,
742 // i.e. bad
743 frame.set_ntp_time_ms(fake_clock_.CurrentNtpInMilliseconds());
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200744 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
sprang948b2752017-05-04 02:47:13 -0700745 VideoContentType::UNSPECIFIED);
746 statistics_proxy_->OnRenderedFrame(frame);
747 fake_clock_.AdvanceTimeMilliseconds(1000 / kDefaultFps);
748 }
749
750 EXPECT_EQ(kDefaultFps, statistics_proxy_->GetStats().decode_frame_rate);
751 EXPECT_EQ(kDefaultFps, statistics_proxy_->GetStats().render_frame_rate);
752
753 // FPS trackers in stats proxy have a 1000ms sliding window.
754 fake_clock_.AdvanceTimeMilliseconds(1000);
755 EXPECT_EQ(0, statistics_proxy_->GetStats().decode_frame_rate);
756 EXPECT_EQ(0, statistics_proxy_->GetStats().render_frame_rate);
757}
758
asapersson2077f2f2017-05-11 05:37:35 -0700759TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsReceivedFrameStats) {
asapersson2077f2f2017-05-11 05:37:35 -0700760 EXPECT_EQ(0, statistics_proxy_->GetStats().width);
761 EXPECT_EQ(0, statistics_proxy_->GetStats().height);
762 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_rendered);
763
764 statistics_proxy_->OnRenderedFrame(CreateFrame(kWidth, kHeight));
765
766 EXPECT_EQ(kWidth, statistics_proxy_->GetStats().width);
767 EXPECT_EQ(kHeight, statistics_proxy_->GetStats().height);
768 EXPECT_EQ(1u, statistics_proxy_->GetStats().frames_rendered);
769}
770
771TEST_F(ReceiveStatisticsProxyTest,
772 ReceivedFrameHistogramsAreNotUpdatedForTooFewSamples) {
asapersson2077f2f2017-05-11 05:37:35 -0700773 for (int i = 0; i < kMinRequiredSamples - 1; ++i)
774 statistics_proxy_->OnRenderedFrame(CreateFrame(kWidth, kHeight));
775
776 statistics_proxy_.reset();
777 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
778 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
779 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
780 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
781}
782
783TEST_F(ReceiveStatisticsProxyTest, ReceivedFrameHistogramsAreUpdated) {
asapersson2077f2f2017-05-11 05:37:35 -0700784 for (int i = 0; i < kMinRequiredSamples; ++i)
785 statistics_proxy_->OnRenderedFrame(CreateFrame(kWidth, kHeight));
786
787 statistics_proxy_.reset();
788 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
789 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
790 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
791 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
792 EXPECT_EQ(1,
793 metrics::NumEvents("WebRTC.Video.ReceivedWidthInPixels", kWidth));
794 EXPECT_EQ(1,
795 metrics::NumEvents("WebRTC.Video.ReceivedHeightInPixels", kHeight));
796}
797
Åsa Persson81327d52018-06-05 13:34:33 +0200798TEST_F(ReceiveStatisticsProxyTest, ZeroDelayReportedIfFrameNotDelayed) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200799 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Åsa Persson81327d52018-06-05 13:34:33 +0200800 VideoContentType::UNSPECIFIED);
801
802 // Frame not delayed, delayed frames to render: 0%.
803 const int64_t kNowMs = fake_clock_.TimeInMilliseconds();
804 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs));
805
806 // Min run time has passed.
807 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000));
808 statistics_proxy_.reset();
809 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
810 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer", 0));
811 EXPECT_EQ(0, metrics::NumSamples(
812 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
813}
814
815TEST_F(ReceiveStatisticsProxyTest,
816 DelayedFrameHistogramsAreNotUpdatedIfMinRuntimeHasNotPassed) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200817 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Åsa Persson81327d52018-06-05 13:34:33 +0200818 VideoContentType::UNSPECIFIED);
819
820 // Frame not delayed, delayed frames to render: 0%.
821 const int64_t kNowMs = fake_clock_.TimeInMilliseconds();
822 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs));
823
824 // Min run time has not passed.
825 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000) -
826 1);
827 statistics_proxy_.reset();
828 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
829 EXPECT_EQ(0, metrics::NumSamples(
830 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
831}
832
833TEST_F(ReceiveStatisticsProxyTest,
834 DelayedFramesHistogramsAreNotUpdatedIfNoRenderedFrames) {
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 // Min run time has passed. No rendered frames.
839 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000));
840 statistics_proxy_.reset();
841 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
842 EXPECT_EQ(0, metrics::NumSamples(
843 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
844}
845
846TEST_F(ReceiveStatisticsProxyTest, DelayReportedIfFrameIsDelayed) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200847 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Åsa Persson81327d52018-06-05 13:34:33 +0200848 VideoContentType::UNSPECIFIED);
849
850 // Frame delayed 1 ms, delayed frames to render: 100%.
851 const int64_t kNowMs = fake_clock_.TimeInMilliseconds();
852 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs - 1));
853
854 // Min run time has passed.
855 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000));
856 statistics_proxy_.reset();
857 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
858 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer", 100));
859 EXPECT_EQ(1, metrics::NumSamples(
860 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
861 EXPECT_EQ(1, metrics::NumEvents(
862 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs", 1));
863}
864
865TEST_F(ReceiveStatisticsProxyTest, AverageDelayOfDelayedFramesIsReported) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200866 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Åsa Persson81327d52018-06-05 13:34:33 +0200867 VideoContentType::UNSPECIFIED);
868
869 // Two frames delayed (6 ms, 10 ms), delayed frames to render: 50%.
870 const int64_t kNowMs = fake_clock_.TimeInMilliseconds();
871 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs - 10));
872 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs - 6));
873 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs));
874 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs + 1));
875
876 // Min run time has passed.
877 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000));
878 statistics_proxy_.reset();
879 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
880 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer", 50));
881 EXPECT_EQ(1, metrics::NumSamples(
882 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
883 EXPECT_EQ(1, metrics::NumEvents(
884 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs", 8));
885}
886
asapersson2077f2f2017-05-11 05:37:35 -0700887TEST_F(ReceiveStatisticsProxyTest,
888 RtcpHistogramsNotUpdatedIfMinRuntimeHasNotPassed) {
889 InsertFirstRtpPacket(kRemoteSsrc);
890 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000) -
891 1);
892
893 RtcpPacketTypeCounter counter;
894 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc, counter);
895
896 statistics_proxy_.reset();
897 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
898 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
899 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
900}
901
902TEST_F(ReceiveStatisticsProxyTest, RtcpHistogramsAreUpdated) {
903 InsertFirstRtpPacket(kRemoteSsrc);
904 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
905
906 const uint32_t kFirPackets = 100;
907 const uint32_t kPliPackets = 200;
908 const uint32_t kNackPackets = 300;
909
910 RtcpPacketTypeCounter counter;
911 counter.fir_packets = kFirPackets;
912 counter.pli_packets = kPliPackets;
913 counter.nack_packets = kNackPackets;
914 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc, counter);
915
916 statistics_proxy_.reset();
917 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
918 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
919 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
920 EXPECT_EQ(
921 1, metrics::NumEvents("WebRTC.Video.FirPacketsSentPerMinute",
922 kFirPackets * 60 / metrics::kMinRunTimeInSeconds));
923 EXPECT_EQ(
924 1, metrics::NumEvents("WebRTC.Video.PliPacketsSentPerMinute",
925 kPliPackets * 60 / metrics::kMinRunTimeInSeconds));
926 EXPECT_EQ(
927 1, metrics::NumEvents("WebRTC.Video.NackPacketsSentPerMinute",
928 kNackPackets * 60 / metrics::kMinRunTimeInSeconds));
929}
930
sprang892dab52017-08-15 05:00:33 -0700931INSTANTIATE_TEST_CASE_P(ContentTypes,
932 ReceiveStatisticsProxyTest,
933 ::testing::Values(VideoContentType::UNSPECIFIED,
934 VideoContentType::SCREENSHARE));
935
936TEST_P(ReceiveStatisticsProxyTest, InterFrameDelaysAreReported) {
937 const VideoContentType content_type = GetParam();
938 const int kInterFrameDelayMs = 33;
939 for (int i = 0; i < kMinRequiredSamples; ++i) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200940 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200941 content_type);
sprang892dab52017-08-15 05:00:33 -0700942 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
943 }
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +0200944 // One extra with double the interval.
sprang892dab52017-08-15 05:00:33 -0700945 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200946 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200947 content_type);
sprang892dab52017-08-15 05:00:33 -0700948
949 statistics_proxy_.reset();
950 const int kExpectedInterFrame =
951 (kInterFrameDelayMs * (kMinRequiredSamples - 1) +
952 kInterFrameDelayMs * 2) /
953 kMinRequiredSamples;
ilnik6d5b4d62017-08-30 03:32:14 -0700954 if (videocontenttypehelpers::IsScreenshare(content_type)) {
955 EXPECT_EQ(
956 kExpectedInterFrame,
957 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs"));
958 EXPECT_EQ(
959 kInterFrameDelayMs * 2,
960 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
961 } else {
962 EXPECT_EQ(kExpectedInterFrame,
963 metrics::MinSample("WebRTC.Video.InterframeDelayInMs"));
964 EXPECT_EQ(kInterFrameDelayMs * 2,
965 metrics::MinSample("WebRTC.Video.InterframeDelayMaxInMs"));
sprang892dab52017-08-15 05:00:33 -0700966 }
967}
968
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +0200969TEST_P(ReceiveStatisticsProxyTest, InterFrameDelaysPercentilesAreReported) {
970 const VideoContentType content_type = GetParam();
971 const int kInterFrameDelayMs = 33;
972 const int kLastFivePercentsSamples = kMinRequiredSamples * 5 / 100;
973 for (int i = 0; i <= kMinRequiredSamples - kLastFivePercentsSamples; ++i) {
974 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200975 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200976 content_type);
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +0200977 }
978 // Last 5% of intervals are double in size.
979 for (int i = 0; i < kLastFivePercentsSamples; ++i) {
980 fake_clock_.AdvanceTimeMilliseconds(2 * kInterFrameDelayMs);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200981 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200982 content_type);
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +0200983 }
984 // Final sample is outlier and 10 times as big.
985 fake_clock_.AdvanceTimeMilliseconds(10 * kInterFrameDelayMs);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200986 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200987 content_type);
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +0200988
989 statistics_proxy_.reset();
990 const int kExpectedInterFrame = kInterFrameDelayMs * 2;
991 if (videocontenttypehelpers::IsScreenshare(content_type)) {
992 EXPECT_EQ(kExpectedInterFrame,
993 metrics::MinSample(
994 "WebRTC.Video.Screenshare.InterframeDelay95PercentileInMs"));
995 } else {
996 EXPECT_EQ(
997 kExpectedInterFrame,
998 metrics::MinSample("WebRTC.Video.InterframeDelay95PercentileInMs"));
999 }
1000}
1001
sprang892dab52017-08-15 05:00:33 -07001002TEST_P(ReceiveStatisticsProxyTest, MaxInterFrameDelayOnlyWithValidAverage) {
1003 const VideoContentType content_type = GetParam();
1004 const int kInterFrameDelayMs = 33;
1005 for (int i = 0; i < kMinRequiredSamples; ++i) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +02001006 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001007 content_type);
sprang892dab52017-08-15 05:00:33 -07001008 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1009 }
1010
1011 // |kMinRequiredSamples| samples, and thereby intervals, is required. That
1012 // means we're one frame short of having a valid data set.
1013 statistics_proxy_.reset();
1014 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
1015 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
1016 EXPECT_EQ(
1017 0, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1018 EXPECT_EQ(0, metrics::NumSamples(
1019 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1020}
1021
sprang3e86e7e2017-08-22 09:23:28 -07001022TEST_P(ReceiveStatisticsProxyTest, MaxInterFrameDelayOnlyWithPause) {
1023 const VideoContentType content_type = GetParam();
1024 const int kInterFrameDelayMs = 33;
1025 for (int i = 0; i <= kMinRequiredSamples; ++i) {
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);
1029 }
1030
1031 // At this state, we should have a valid inter-frame delay.
1032 // Indicate stream paused and make a large jump in time.
1033 statistics_proxy_->OnStreamInactive();
1034 fake_clock_.AdvanceTimeMilliseconds(5000);
1035
1036 // Insert two more frames. The interval during the pause should be disregarded
1037 // in the stats.
Danil Chapovalovb9b146c2018-06-15 12:28:07 +02001038 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001039 content_type);
sprang3e86e7e2017-08-22 09:23:28 -07001040 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +02001041 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001042 content_type);
sprang3e86e7e2017-08-22 09:23:28 -07001043
1044 statistics_proxy_.reset();
ilnik6d5b4d62017-08-30 03:32:14 -07001045 if (videocontenttypehelpers::IsScreenshare(content_type)) {
sprang3e86e7e2017-08-22 09:23:28 -07001046 EXPECT_EQ(
1047 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1048 EXPECT_EQ(1, metrics::NumSamples(
1049 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1050 EXPECT_EQ(
1051 kInterFrameDelayMs,
1052 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1053 EXPECT_EQ(
1054 kInterFrameDelayMs,
1055 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1056 } else {
1057 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
1058 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
1059 EXPECT_EQ(kInterFrameDelayMs,
1060 metrics::MinSample("WebRTC.Video.InterframeDelayInMs"));
1061 EXPECT_EQ(kInterFrameDelayMs,
1062 metrics::MinSample("WebRTC.Video.InterframeDelayMaxInMs"));
1063 }
1064}
1065
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001066TEST_P(ReceiveStatisticsProxyTest, FreezesAreReported) {
1067 const VideoContentType content_type = GetParam();
1068 const int kInterFrameDelayMs = 33;
1069 const int kFreezeDelayMs = 200;
1070 for (int i = 0; i < kMinRequiredSamples; ++i) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +02001071 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001072 content_type);
1073 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1074 }
1075 // Add extra freeze.
1076 fake_clock_.AdvanceTimeMilliseconds(kFreezeDelayMs);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +02001077 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001078 content_type);
1079
1080 statistics_proxy_.reset();
1081 const int kExpectedTimeBetweenFreezes =
1082 kInterFrameDelayMs * (kMinRequiredSamples - 1);
1083 if (videocontenttypehelpers::IsScreenshare(content_type)) {
1084 EXPECT_EQ(
1085 kFreezeDelayMs + kInterFrameDelayMs,
1086 metrics::MinSample("WebRTC.Video.Screenshare.MeanFreezeDurationMs"));
1087 EXPECT_EQ(kExpectedTimeBetweenFreezes,
1088 metrics::MinSample(
1089 "WebRTC.Video.Screenshare.MeanTimeBetweenFreezesMs"));
1090 } else {
1091 EXPECT_EQ(kFreezeDelayMs + kInterFrameDelayMs,
1092 metrics::MinSample("WebRTC.Video.MeanFreezeDurationMs"));
1093 EXPECT_EQ(kExpectedTimeBetweenFreezes,
1094 metrics::MinSample("WebRTC.Video.MeanTimeBetweenFreezesMs"));
1095 }
1096}
1097
1098TEST_P(ReceiveStatisticsProxyTest, PausesAreIgnored) {
1099 const VideoContentType content_type = GetParam();
1100 const int kInterFrameDelayMs = 33;
1101 const int kPauseDurationMs = 10000;
1102 for (int i = 0; i <= kMinRequiredSamples; ++i) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +02001103 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001104 content_type);
1105 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1106 }
1107 // Add a pause.
1108 fake_clock_.AdvanceTimeMilliseconds(kPauseDurationMs);
1109 statistics_proxy_->OnStreamInactive();
1110
1111 // Second playback interval with triple the length.
1112 for (int i = 0; i <= kMinRequiredSamples * 3; ++i) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +02001113 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001114 content_type);
1115 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1116 }
1117
1118 statistics_proxy_.reset();
1119 // Average of two playback intervals.
1120 const int kExpectedTimeBetweenFreezes =
1121 kInterFrameDelayMs * kMinRequiredSamples * 2;
1122 if (videocontenttypehelpers::IsScreenshare(content_type)) {
1123 EXPECT_EQ(-1, metrics::MinSample(
1124 "WebRTC.Video.Screenshare.MeanFreezeDurationMs"));
1125 EXPECT_EQ(kExpectedTimeBetweenFreezes,
1126 metrics::MinSample(
1127 "WebRTC.Video.Screenshare.MeanTimeBetweenFreezesMs"));
1128 } else {
1129 EXPECT_EQ(-1, metrics::MinSample("WebRTC.Video.MeanFreezeDurationMs"));
1130 EXPECT_EQ(kExpectedTimeBetweenFreezes,
1131 metrics::MinSample("WebRTC.Video.MeanTimeBetweenFreezesMs"));
1132 }
1133}
1134
Ilya Nikolaevskiy879f5a32018-05-31 09:47:17 +02001135TEST_P(ReceiveStatisticsProxyTest, ManyPausesAtTheBeginning) {
1136 const VideoContentType content_type = GetParam();
1137 const int kInterFrameDelayMs = 33;
1138 const int kPauseDurationMs = 10000;
1139 for (int i = 0; i <= kMinRequiredSamples; ++i) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +02001140 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy879f5a32018-05-31 09:47:17 +02001141 content_type);
1142 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1143
1144 statistics_proxy_->OnStreamInactive();
1145 fake_clock_.AdvanceTimeMilliseconds(kPauseDurationMs);
1146
Danil Chapovalovb9b146c2018-06-15 12:28:07 +02001147 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
1148 content_type);
Ilya Nikolaevskiy879f5a32018-05-31 09:47:17 +02001149 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1150 }
1151
1152 statistics_proxy_.reset();
1153 // No freezes should be detected, as all long inter-frame delays were pauses.
1154 if (videocontenttypehelpers::IsScreenshare(content_type)) {
1155 EXPECT_EQ(-1, metrics::MinSample(
1156 "WebRTC.Video.Screenshare.MeanFreezeDurationMs"));
1157 } else {
1158 EXPECT_EQ(-1, metrics::MinSample("WebRTC.Video.MeanFreezeDurationMs"));
1159 }
1160}
1161
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001162TEST_P(ReceiveStatisticsProxyTest, TimeInHdReported) {
1163 const VideoContentType content_type = GetParam();
1164 const int kInterFrameDelayMs = 20;
1165 // HD frames.
1166 for (int i = 0; i < kMinRequiredSamples; ++i) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +02001167 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001168 content_type);
1169 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1170 }
1171 // SD frames.
1172 for (int i = 0; i < 2 * kMinRequiredSamples; ++i) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +02001173 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth / 2, kHeight / 2,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001174 content_type);
1175 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1176 }
1177 // Extra last frame.
Danil Chapovalovb9b146c2018-06-15 12:28:07 +02001178 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth / 2, kHeight / 2,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001179 content_type);
1180 statistics_proxy_.reset();
1181 const int kExpectedTimeInHdPercents = 33;
1182 if (videocontenttypehelpers::IsScreenshare(content_type)) {
1183 EXPECT_EQ(
1184 kExpectedTimeInHdPercents,
1185 metrics::MinSample("WebRTC.Video.Screenshare.TimeInHdPercentage"));
1186 } else {
1187 EXPECT_EQ(kExpectedTimeInHdPercents,
1188 metrics::MinSample("WebRTC.Video.TimeInHdPercentage"));
1189 }
1190}
1191
1192TEST_P(ReceiveStatisticsProxyTest, TimeInBlockyVideoReported) {
1193 const VideoContentType content_type = GetParam();
1194 const int kInterFrameDelayMs = 20;
1195 const int kHighQp = 80;
1196 const int kLowQp = 30;
1197 // High quality frames.
1198 for (int i = 0; i < kMinRequiredSamples; ++i) {
1199 statistics_proxy_->OnDecodedFrame(kLowQp, kWidth, kHeight, content_type);
1200 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1201 }
1202 // Blocky frames.
1203 for (int i = 0; i < 2 * kMinRequiredSamples; ++i) {
1204 statistics_proxy_->OnDecodedFrame(kHighQp, kWidth, kHeight, content_type);
1205 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1206 }
1207 // Extra last frame.
1208 statistics_proxy_->OnDecodedFrame(kHighQp, kWidth, kHeight, content_type);
1209 statistics_proxy_.reset();
1210 const int kExpectedTimeInHdPercents = 66;
1211 if (videocontenttypehelpers::IsScreenshare(content_type)) {
1212 EXPECT_EQ(kExpectedTimeInHdPercents,
1213 metrics::MinSample(
1214 "WebRTC.Video.Screenshare.TimeInBlockyVideoPercentage"));
1215 } else {
1216 EXPECT_EQ(kExpectedTimeInHdPercents,
1217 metrics::MinSample("WebRTC.Video.TimeInBlockyVideoPercentage"));
1218 }
1219}
1220
1221TEST_P(ReceiveStatisticsProxyTest, DownscalesReported) {
1222 const VideoContentType content_type = GetParam();
1223 const int kInterFrameDelayMs = 1000; // To ensure long enough call duration.
1224 const int kLowQp = 30;
1225
1226 statistics_proxy_->OnDecodedFrame(kLowQp, kWidth / 2, kHeight / 2,
1227 content_type);
1228 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1229
1230 // Downscale.
1231 statistics_proxy_->OnDecodedFrame(kLowQp, kWidth, kHeight, 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 statistics_proxy_->OnDecodedFrame(kLowQp, kWidth / 2, kHeight / 2,
1239 content_type);
1240 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1241
1242 // Downscale.
1243 statistics_proxy_->OnDecodedFrame(kLowQp, kWidth / 4, kHeight / 4,
1244 content_type);
1245 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1246
1247 statistics_proxy_.reset();
1248 const int kExpectedDownscales = 30; // 2 per 5 seconds = 30 per minute.
1249 if (videocontenttypehelpers::IsScreenshare(content_type)) {
1250 EXPECT_EQ(
1251 kExpectedDownscales,
1252 metrics::MinSample(
1253 "WebRTC.Video.Screenshare.NumberResolutionDownswitchesPerMinute"));
1254 } else {
1255 EXPECT_EQ(kExpectedDownscales,
1256 metrics::MinSample(
1257 "WebRTC.Video.NumberResolutionDownswitchesPerMinute"));
1258 }
1259}
1260
ilnik6d5b4d62017-08-30 03:32:14 -07001261TEST_P(ReceiveStatisticsProxyTest, StatsAreSlicedOnSimulcastAndExperiment) {
1262 VideoContentType content_type = GetParam();
1263 const uint8_t experiment_id = 1;
1264 videocontenttypehelpers::SetExperimentId(&content_type, experiment_id);
1265 const int kInterFrameDelayMs1 = 30;
1266 const int kInterFrameDelayMs2 = 50;
1267
1268 videocontenttypehelpers::SetSimulcastId(&content_type, 1);
1269 for (int i = 0; i <= kMinRequiredSamples; ++i) {
1270 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs1);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +02001271 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001272 content_type);
ilnik6d5b4d62017-08-30 03:32:14 -07001273 }
1274
1275 videocontenttypehelpers::SetSimulcastId(&content_type, 2);
1276 for (int i = 0; i <= kMinRequiredSamples; ++i) {
1277 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs2);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +02001278 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001279 content_type);
ilnik6d5b4d62017-08-30 03:32:14 -07001280 }
1281 statistics_proxy_.reset();
1282
1283 if (videocontenttypehelpers::IsScreenshare(content_type)) {
1284 EXPECT_EQ(
1285 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1286 EXPECT_EQ(1, metrics::NumSamples(
1287 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1288 EXPECT_EQ(1, metrics::NumSamples(
1289 "WebRTC.Video.Screenshare.InterframeDelayInMs.S0"));
1290 EXPECT_EQ(1, metrics::NumSamples(
1291 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs.S0"));
1292 EXPECT_EQ(1, metrics::NumSamples(
1293 "WebRTC.Video.Screenshare.InterframeDelayInMs.S1"));
1294 EXPECT_EQ(1, metrics::NumSamples(
1295 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs.S1"));
1296 EXPECT_EQ(1,
1297 metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"
1298 ".ExperimentGroup0"));
1299 EXPECT_EQ(
1300 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"
1301 ".ExperimentGroup0"));
1302 EXPECT_EQ(
1303 kInterFrameDelayMs1,
1304 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs.S0"));
1305 EXPECT_EQ(
1306 kInterFrameDelayMs2,
1307 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs.S1"));
1308 EXPECT_EQ(
1309 (kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1310 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1311 EXPECT_EQ(
1312 kInterFrameDelayMs2,
1313 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1314 EXPECT_EQ(
1315 (kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1316 metrics::MinSample(
1317 "WebRTC.Video.Screenshare.InterframeDelayInMs.ExperimentGroup0"));
1318 } else {
1319 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
1320 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
1321 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs.S0"));
1322 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs.S0"));
1323 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs.S1"));
1324 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs.S1"));
1325 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"
1326 ".ExperimentGroup0"));
1327 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"
1328 ".ExperimentGroup0"));
1329 EXPECT_EQ(kInterFrameDelayMs1,
1330 metrics::MinSample("WebRTC.Video.InterframeDelayInMs.S0"));
1331 EXPECT_EQ(kInterFrameDelayMs2,
1332 metrics::MinSample("WebRTC.Video.InterframeDelayInMs.S1"));
1333 EXPECT_EQ((kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1334 metrics::MinSample("WebRTC.Video.InterframeDelayInMs"));
1335 EXPECT_EQ(kInterFrameDelayMs2,
1336 metrics::MinSample("WebRTC.Video.InterframeDelayMaxInMs"));
1337 EXPECT_EQ((kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1338 metrics::MinSample(
1339 "WebRTC.Video.InterframeDelayInMs.ExperimentGroup0"));
1340 }
1341}
sakale5ba44e2016-10-26 07:09:24 -07001342} // namespace webrtc