blob: a0f515b85fe3a93a1497ad83bf40f68f5b1f6238 [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>
Yves Gerey3e707812018-11-28 16:47:49 +010015#include <string>
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"
Yves Gerey3e707812018-11-28 16:47:49 +010019#include "api/video/video_frame_buffer.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#include "api/video/video_rotation.h"
Yves Gerey3e707812018-11-28 16:47:49 +010021#include "rtc_base/scoped_ref_ptr.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020022#include "system_wrappers/include/metrics.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020023#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) {
Artem Titov1ebfb6a2019-01-03 23:49:37 +010071 VideoFrame frame =
72 VideoFrame::Builder()
73 .set_video_frame_buffer(I420Buffer::Create(width, height))
74 .set_timestamp_rtp(0)
75 .set_timestamp_ms(render_time_ms)
76 .set_rotation(kVideoRotation_0)
77 .build();
asapersson2077f2f2017-05-11 05:37:35 -070078 frame.set_ntp_time_ms(fake_clock_.CurrentNtpInMilliseconds());
79 return frame;
80 }
81
sakale5ba44e2016-10-26 07:09:24 -070082 SimulatedClock fake_clock_;
asaperssonde9e5ff2016-11-02 07:14:03 -070083 const VideoReceiveStream::Config config_;
sakale5ba44e2016-10-26 07:09:24 -070084 std::unique_ptr<ReceiveStatisticsProxy> statistics_proxy_;
sakale5ba44e2016-10-26 07:09:24 -070085};
86
87TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameIncreasesFramesDecoded) {
88 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_decoded);
89 for (uint32_t i = 1; i <= 3; ++i) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +020090 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
ilnik00d802b2017-04-11 10:34:31 -070091 VideoContentType::UNSPECIFIED);
sakale5ba44e2016-10-26 07:09:24 -070092 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_decoded);
93 }
94}
95
Åsa Perssonb9b07ea2018-01-24 17:04:07 +010096TEST_F(ReceiveStatisticsProxyTest, DecodedFpsIsReported) {
97 const int kFps = 20;
98 const int kRequiredSamples = metrics::kMinRunTimeInSeconds * kFps;
99 for (int i = 0; i < kRequiredSamples; ++i) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200100 statistics_proxy_->OnDecodedFrame(absl::optional<uint8_t>(), kWidth,
101 kHeight, VideoContentType::UNSPECIFIED);
Åsa Perssonb9b07ea2018-01-24 17:04:07 +0100102 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
103 }
104 statistics_proxy_.reset();
105 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
106 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DecodedFramesPerSecond", kFps));
107}
108
109TEST_F(ReceiveStatisticsProxyTest, DecodedFpsIsNotReportedForTooFewSamples) {
110 const int kFps = 20;
111 const int kRequiredSamples = metrics::kMinRunTimeInSeconds * kFps;
112 for (int i = 0; i < kRequiredSamples - 1; ++i) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200113 statistics_proxy_->OnDecodedFrame(absl::optional<uint8_t>(), kWidth,
114 kHeight, VideoContentType::UNSPECIFIED);
Åsa Perssonb9b07ea2018-01-24 17:04:07 +0100115 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
116 }
117 statistics_proxy_.reset();
118 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
119}
120
121TEST_F(ReceiveStatisticsProxyTest, DecodedFpsIsReportedWithQpReset) {
122 const int kFps1 = 10;
123 for (int i = 0; i < metrics::kMinRunTimeInSeconds * kFps1; ++i) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200124 statistics_proxy_->OnDecodedFrame(absl::optional<uint8_t>(), kWidth,
125 kHeight, VideoContentType::UNSPECIFIED);
Åsa Perssonb9b07ea2018-01-24 17:04:07 +0100126 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps1);
127 }
128 // First QP value received, resets frames decoded.
129 const int kFps2 = 20;
130 for (int i = 0; i < metrics::kMinRunTimeInSeconds * kFps2; ++i) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200131 statistics_proxy_->OnDecodedFrame(absl::optional<uint8_t>(1u), kWidth,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200132 kHeight, VideoContentType::UNSPECIFIED);
Åsa Perssonb9b07ea2018-01-24 17:04:07 +0100133 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps2);
134 }
135 statistics_proxy_.reset();
136 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
137 EXPECT_EQ(1,
138 metrics::NumEvents("WebRTC.Video.DecodedFramesPerSecond", kFps2));
139}
140
sakalcc452e12017-02-09 04:53:45 -0800141TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameWithQpResetsFramesDecoded) {
142 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_decoded);
143 for (uint32_t i = 1; i <= 3; ++i) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200144 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
ilnik00d802b2017-04-11 10:34:31 -0700145 VideoContentType::UNSPECIFIED);
sakalcc452e12017-02-09 04:53:45 -0800146 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_decoded);
147 }
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200148 statistics_proxy_->OnDecodedFrame(1u, kWidth, kHeight,
149 VideoContentType::UNSPECIFIED);
sakalcc452e12017-02-09 04:53:45 -0800150 EXPECT_EQ(1u, statistics_proxy_->GetStats().frames_decoded);
151}
152
153TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameIncreasesQpSum) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200154 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200155 statistics_proxy_->OnDecodedFrame(3u, kWidth, kHeight,
156 VideoContentType::UNSPECIFIED);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100157 EXPECT_EQ(3u, statistics_proxy_->GetStats().qp_sum);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200158 statistics_proxy_->OnDecodedFrame(127u, kWidth, kHeight,
159 VideoContentType::UNSPECIFIED);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100160 EXPECT_EQ(130u, statistics_proxy_->GetStats().qp_sum);
sakalcc452e12017-02-09 04:53:45 -0800161}
162
ilnik2e1b40b2017-09-04 07:57:17 -0700163TEST_F(ReceiveStatisticsProxyTest, ReportsContentType) {
164 const std::string kRealtimeString("realtime");
165 const std::string kScreenshareString("screen");
166 EXPECT_EQ(kRealtimeString, videocontenttypehelpers::ToString(
167 statistics_proxy_->GetStats().content_type));
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200168 statistics_proxy_->OnDecodedFrame(3u, kWidth, kHeight,
169 VideoContentType::SCREENSHARE);
ilnik2e1b40b2017-09-04 07:57:17 -0700170 EXPECT_EQ(kScreenshareString, videocontenttypehelpers::ToString(
171 statistics_proxy_->GetStats().content_type));
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200172 statistics_proxy_->OnDecodedFrame(3u, kWidth, kHeight,
173 VideoContentType::UNSPECIFIED);
ilnik2e1b40b2017-09-04 07:57:17 -0700174 EXPECT_EQ(kRealtimeString, videocontenttypehelpers::ToString(
175 statistics_proxy_->GetStats().content_type));
176}
177
ilnika79cc282017-08-23 05:24:10 -0700178TEST_F(ReceiveStatisticsProxyTest, ReportsMaxInterframeDelay) {
179 const int64_t kInterframeDelayMs1 = 100;
180 const int64_t kInterframeDelayMs2 = 200;
181 const int64_t kInterframeDelayMs3 = 100;
182 EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200183 statistics_proxy_->OnDecodedFrame(3u, kWidth, kHeight,
184 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700185 EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
ilnikf04afde2017-07-07 01:26:24 -0700186
187 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs1);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200188 statistics_proxy_->OnDecodedFrame(127u, kWidth, kHeight,
189 VideoContentType::UNSPECIFIED);
ilnikf04afde2017-07-07 01:26:24 -0700190 EXPECT_EQ(kInterframeDelayMs1,
ilnika79cc282017-08-23 05:24:10 -0700191 statistics_proxy_->GetStats().interframe_delay_max_ms);
ilnikf04afde2017-07-07 01:26:24 -0700192
193 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs2);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200194 statistics_proxy_->OnDecodedFrame(127u, kWidth, kHeight,
195 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700196 EXPECT_EQ(kInterframeDelayMs2,
197 statistics_proxy_->GetStats().interframe_delay_max_ms);
198
199 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs3);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200200 statistics_proxy_->OnDecodedFrame(127u, kWidth, kHeight,
201 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700202 // kInterframeDelayMs3 is smaller than kInterframeDelayMs2.
203 EXPECT_EQ(kInterframeDelayMs2,
204 statistics_proxy_->GetStats().interframe_delay_max_ms);
205}
206
207TEST_F(ReceiveStatisticsProxyTest, ReportInterframeDelayInWindow) {
Ilya Nikolaevskiyb06b3582017-10-16 17:59:12 +0200208 const int64_t kInterframeDelayMs1 = 900;
209 const int64_t kInterframeDelayMs2 = 750;
210 const int64_t kInterframeDelayMs3 = 700;
ilnika79cc282017-08-23 05:24:10 -0700211 EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200212 statistics_proxy_->OnDecodedFrame(3u, kWidth, kHeight,
213 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700214 EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
215
216 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs1);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200217 statistics_proxy_->OnDecodedFrame(127u, kWidth, kHeight,
218 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700219 EXPECT_EQ(kInterframeDelayMs1,
220 statistics_proxy_->GetStats().interframe_delay_max_ms);
221
222 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs2);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200223 statistics_proxy_->OnDecodedFrame(127u, kWidth, kHeight,
224 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700225 // Still first delay is the maximum
226 EXPECT_EQ(kInterframeDelayMs1,
227 statistics_proxy_->GetStats().interframe_delay_max_ms);
228
229 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs3);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200230 statistics_proxy_->OnDecodedFrame(127u, kWidth, kHeight,
231 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700232 // Now the first sample is out of the window, so the second is the maximum.
233 EXPECT_EQ(kInterframeDelayMs2,
234 statistics_proxy_->GetStats().interframe_delay_max_ms);
ilnikf04afde2017-07-07 01:26:24 -0700235}
236
sakalcc452e12017-02-09 04:53:45 -0800237TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameWithoutQpQpSumWontExist) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200238 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
239 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
ilnik00d802b2017-04-11 10:34:31 -0700240 VideoContentType::UNSPECIFIED);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200241 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakalcc452e12017-02-09 04:53:45 -0800242}
243
244TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameWithoutQpResetsQpSum) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200245 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200246 statistics_proxy_->OnDecodedFrame(3u, kWidth, kHeight,
247 VideoContentType::UNSPECIFIED);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100248 EXPECT_EQ(3u, statistics_proxy_->GetStats().qp_sum);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200249 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
ilnik00d802b2017-04-11 10:34:31 -0700250 VideoContentType::UNSPECIFIED);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200251 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakalcc452e12017-02-09 04:53:45 -0800252}
253
hbos50cfe1f2017-01-23 07:21:55 -0800254TEST_F(ReceiveStatisticsProxyTest, OnRenderedFrameIncreasesFramesRendered) {
255 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_rendered);
Artem Titov1ebfb6a2019-01-03 23:49:37 +0100256 webrtc::VideoFrame frame =
257 VideoFrame::Builder()
258 .set_video_frame_buffer(webrtc::I420Buffer::Create(1, 1))
259 .set_timestamp_rtp(0)
260 .set_timestamp_us(0)
261 .set_rotation(kVideoRotation_0)
262 .build();
hbos50cfe1f2017-01-23 07:21:55 -0800263 for (uint32_t i = 1; i <= 3; ++i) {
264 statistics_proxy_->OnRenderedFrame(frame);
265 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_rendered);
266 }
267}
268
asapersson46c4e3c2016-11-03 06:48:19 -0700269TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsSsrc) {
270 EXPECT_EQ(kRemoteSsrc, statistics_proxy_->GetStats().ssrc);
271}
272
273TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsIncomingPayloadType) {
274 const int kPayloadType = 111;
275 statistics_proxy_->OnIncomingPayloadType(kPayloadType);
276 EXPECT_EQ(kPayloadType, statistics_proxy_->GetStats().current_payload_type);
277}
278
asapersson6966bd52017-01-03 00:44:06 -0800279TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsDecoderImplementationName) {
280 const char* kName = "decoderName";
281 statistics_proxy_->OnDecoderImplementationName(kName);
282 EXPECT_STREQ(
283 kName, statistics_proxy_->GetStats().decoder_implementation_name.c_str());
284}
285
philipela45102f2017-02-22 05:30:39 -0800286TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsOnCompleteFrame) {
287 const int kFrameSizeBytes = 1000;
ilnik6d5b4d62017-08-30 03:32:14 -0700288 statistics_proxy_->OnCompleteFrame(true, kFrameSizeBytes,
289 VideoContentType::UNSPECIFIED);
philipela45102f2017-02-22 05:30:39 -0800290 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
291 EXPECT_EQ(1, stats.network_frame_rate);
philipela45102f2017-02-22 05:30:39 -0800292 EXPECT_EQ(1, stats.frame_counts.key_frames);
293 EXPECT_EQ(0, stats.frame_counts.delta_frames);
asapersson46c4e3c2016-11-03 06:48:19 -0700294}
295
296TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsDecodeTimingStats) {
297 const int kDecodeMs = 1;
298 const int kMaxDecodeMs = 2;
299 const int kCurrentDelayMs = 3;
300 const int kTargetDelayMs = 4;
301 const int kJitterBufferMs = 5;
302 const int kMinPlayoutDelayMs = 6;
303 const int kRenderDelayMs = 7;
304 const int64_t kRttMs = 8;
philipela45102f2017-02-22 05:30:39 -0800305 statistics_proxy_->OnRttUpdate(kRttMs, 0);
306 statistics_proxy_->OnFrameBufferTimingsUpdated(
asapersson46c4e3c2016-11-03 06:48:19 -0700307 kDecodeMs, kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs, kJitterBufferMs,
philipela45102f2017-02-22 05:30:39 -0800308 kMinPlayoutDelayMs, kRenderDelayMs);
asapersson46c4e3c2016-11-03 06:48:19 -0700309 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
310 EXPECT_EQ(kDecodeMs, stats.decode_ms);
311 EXPECT_EQ(kMaxDecodeMs, stats.max_decode_ms);
312 EXPECT_EQ(kCurrentDelayMs, stats.current_delay_ms);
313 EXPECT_EQ(kTargetDelayMs, stats.target_delay_ms);
314 EXPECT_EQ(kJitterBufferMs, stats.jitter_buffer_ms);
315 EXPECT_EQ(kMinPlayoutDelayMs, stats.min_playout_delay_ms);
316 EXPECT_EQ(kRenderDelayMs, stats.render_delay_ms);
317}
318
asapersson6966bd52017-01-03 00:44:06 -0800319TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsRtcpPacketTypeCounts) {
320 const uint32_t kFirPackets = 33;
321 const uint32_t kPliPackets = 44;
322 const uint32_t kNackPackets = 55;
323 RtcpPacketTypeCounter counter;
324 counter.fir_packets = kFirPackets;
325 counter.pli_packets = kPliPackets;
326 counter.nack_packets = kNackPackets;
327 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc, counter);
328 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
329 EXPECT_EQ(kFirPackets, stats.rtcp_packet_type_counts.fir_packets);
330 EXPECT_EQ(kPliPackets, stats.rtcp_packet_type_counts.pli_packets);
331 EXPECT_EQ(kNackPackets, stats.rtcp_packet_type_counts.nack_packets);
332}
333
334TEST_F(ReceiveStatisticsProxyTest,
335 GetStatsReportsNoRtcpPacketTypeCountsForUnknownSsrc) {
336 RtcpPacketTypeCounter counter;
337 counter.fir_packets = 33;
338 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc + 1, counter);
339 EXPECT_EQ(0u,
340 statistics_proxy_->GetStats().rtcp_packet_type_counts.fir_packets);
341}
342
343TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsFrameCounts) {
344 const int kKeyFrames = 3;
345 const int kDeltaFrames = 22;
346 FrameCounts frame_counts;
347 frame_counts.key_frames = kKeyFrames;
348 frame_counts.delta_frames = kDeltaFrames;
349 statistics_proxy_->OnFrameCountsUpdated(frame_counts);
350 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
351 EXPECT_EQ(kKeyFrames, stats.frame_counts.key_frames);
352 EXPECT_EQ(kDeltaFrames, stats.frame_counts.delta_frames);
353}
354
asapersson46c4e3c2016-11-03 06:48:19 -0700355TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsDiscardedPackets) {
356 const int kDiscardedPackets = 12;
357 statistics_proxy_->OnDiscardedPacketsUpdated(kDiscardedPackets);
358 EXPECT_EQ(kDiscardedPackets, statistics_proxy_->GetStats().discarded_packets);
359}
360
asapersson6966bd52017-01-03 00:44:06 -0800361TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsRtcpStats) {
362 const uint8_t kFracLost = 0;
Harald Alvestrandc7c41912017-12-08 09:59:34 +0100363 const int32_t kCumLost = 1;
asapersson6966bd52017-01-03 00:44:06 -0800364 const uint32_t kExtSeqNum = 10;
365 const uint32_t kJitter = 4;
366
367 RtcpStatistics rtcp_stats;
368 rtcp_stats.fraction_lost = kFracLost;
srte186d9c32017-08-04 05:03:53 -0700369 rtcp_stats.packets_lost = kCumLost;
370 rtcp_stats.extended_highest_sequence_number = kExtSeqNum;
asapersson6966bd52017-01-03 00:44:06 -0800371 rtcp_stats.jitter = kJitter;
372 statistics_proxy_->StatisticsUpdated(rtcp_stats, kRemoteSsrc);
373
374 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
375 EXPECT_EQ(kFracLost, stats.rtcp_stats.fraction_lost);
srte186d9c32017-08-04 05:03:53 -0700376 EXPECT_EQ(kCumLost, stats.rtcp_stats.packets_lost);
377 EXPECT_EQ(kExtSeqNum, stats.rtcp_stats.extended_highest_sequence_number);
asapersson6966bd52017-01-03 00:44:06 -0800378 EXPECT_EQ(kJitter, stats.rtcp_stats.jitter);
379}
380
381TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsCName) {
382 const char* kName = "cName";
383 statistics_proxy_->CNameChanged(kName, kRemoteSsrc);
384 EXPECT_STREQ(kName, statistics_proxy_->GetStats().c_name.c_str());
385}
386
387TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsNoCNameForUnknownSsrc) {
388 const char* kName = "cName";
389 statistics_proxy_->CNameChanged(kName, kRemoteSsrc + 1);
390 EXPECT_STREQ("", statistics_proxy_->GetStats().c_name.c_str());
391}
392
ilnik2edc6842017-07-06 03:06:50 -0700393TEST_F(ReceiveStatisticsProxyTest,
ilnik75204c52017-09-04 03:35:40 -0700394 ReportsLongestTimingFrameInfo) {
ilnik2edc6842017-07-06 03:06:50 -0700395 const int64_t kShortEndToEndDelay = 10;
396 const int64_t kMedEndToEndDelay = 20;
397 const int64_t kLongEndToEndDelay = 100;
398 const uint32_t kExpectedRtpTimestamp = 2;
399 TimingFrameInfo info;
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200400 absl::optional<TimingFrameInfo> result;
ilnik2edc6842017-07-06 03:06:50 -0700401 info.rtp_timestamp = kExpectedRtpTimestamp - 1;
402 info.capture_time_ms = 0;
403 info.decode_finish_ms = kShortEndToEndDelay;
404 statistics_proxy_->OnTimingFrameInfoUpdated(info);
405 info.rtp_timestamp =
406 kExpectedRtpTimestamp; // this frame should be reported in the end.
407 info.capture_time_ms = 0;
408 info.decode_finish_ms = kLongEndToEndDelay;
409 statistics_proxy_->OnTimingFrameInfoUpdated(info);
410 info.rtp_timestamp = kExpectedRtpTimestamp + 1;
411 info.capture_time_ms = 0;
412 info.decode_finish_ms = kMedEndToEndDelay;
413 statistics_proxy_->OnTimingFrameInfoUpdated(info);
ilnik75204c52017-09-04 03:35:40 -0700414 result = statistics_proxy_->GetStats().timing_frame_info;
ilnik2edc6842017-07-06 03:06:50 -0700415 EXPECT_TRUE(result);
416 EXPECT_EQ(kExpectedRtpTimestamp, result->rtp_timestamp);
417}
418
ilnik75204c52017-09-04 03:35:40 -0700419TEST_F(ReceiveStatisticsProxyTest, RespectsReportingIntervalForTimingFrames) {
420 TimingFrameInfo info;
ilnik2edc6842017-07-06 03:06:50 -0700421 const int64_t kShortEndToEndDelay = 10;
422 const uint32_t kExpectedRtpTimestamp = 2;
ilnik75204c52017-09-04 03:35:40 -0700423 const int64_t kShortDelayMs = 1000;
424 const int64_t kLongDelayMs = 10000;
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200425 absl::optional<TimingFrameInfo> result;
ilnik2edc6842017-07-06 03:06:50 -0700426 info.rtp_timestamp = kExpectedRtpTimestamp;
427 info.capture_time_ms = 0;
428 info.decode_finish_ms = kShortEndToEndDelay;
429 statistics_proxy_->OnTimingFrameInfoUpdated(info);
ilnik75204c52017-09-04 03:35:40 -0700430 fake_clock_.AdvanceTimeMilliseconds(kShortDelayMs);
431 result = statistics_proxy_->GetStats().timing_frame_info;
ilnik2edc6842017-07-06 03:06:50 -0700432 EXPECT_TRUE(result);
433 EXPECT_EQ(kExpectedRtpTimestamp, result->rtp_timestamp);
ilnik75204c52017-09-04 03:35:40 -0700434 fake_clock_.AdvanceTimeMilliseconds(kLongDelayMs);
435 result = statistics_proxy_->GetStats().timing_frame_info;
ilnik2edc6842017-07-06 03:06:50 -0700436 EXPECT_FALSE(result);
437}
438
asapersson46c4e3c2016-11-03 06:48:19 -0700439TEST_F(ReceiveStatisticsProxyTest, LifetimeHistogramIsUpdated) {
440 const int64_t kTimeSec = 3;
441 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
ilnik6d5b4d62017-08-30 03:32:14 -0700442 // Need at least one frame to report stream lifetime.
443 statistics_proxy_->OnCompleteFrame(true, 1000, VideoContentType::UNSPECIFIED);
asapersson46c4e3c2016-11-03 06:48:19 -0700444 // Histograms are updated when the statistics_proxy_ is deleted.
445 statistics_proxy_.reset();
446 EXPECT_EQ(1,
447 metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
448 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.ReceiveStreamLifetimeInSeconds",
449 kTimeSec));
450}
451
ilnik6d5b4d62017-08-30 03:32:14 -0700452TEST_F(ReceiveStatisticsProxyTest,
453 LifetimeHistogramNotReportedForEmptyStreams) {
454 const int64_t kTimeSec = 3;
455 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
456 // No frames received.
457 // Histograms are updated when the statistics_proxy_ is deleted.
458 statistics_proxy_.reset();
459 EXPECT_EQ(0,
460 metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
461}
462
palmkvista40672a2017-01-13 05:58:34 -0800463TEST_F(ReceiveStatisticsProxyTest, BadCallHistogramsAreUpdated) {
464 // Based on the tuning parameters this will produce 7 uncertain states,
465 // then 10 certainly bad states. There has to be 10 certain states before
466 // any histograms are recorded.
467 const int kNumBadSamples = 17;
468
469 StreamDataCounters counters;
470 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
471 statistics_proxy_->DataCountersUpdated(counters, config_.rtp.remote_ssrc);
472
473 for (int i = 0; i < kNumBadSamples; ++i) {
474 // Since OnRenderedFrame is never called the fps in each sample will be 0,
475 // i.e. bad
476 fake_clock_.AdvanceTimeMilliseconds(1000);
477 statistics_proxy_->OnIncomingRate(0, 0);
478 }
479 // Histograms are updated when the statistics_proxy_ is deleted.
480 statistics_proxy_.reset();
481 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BadCall.Any"));
482 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BadCall.Any", 100));
483
484 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BadCall.FrameRate"));
485 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BadCall.FrameRate", 100));
486
487 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.BadCall.FrameRateVariance"));
488
489 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.BadCall.Qp"));
490}
491
asapersson0c43f772016-11-30 01:42:26 -0800492TEST_F(ReceiveStatisticsProxyTest, PacketLossHistogramIsUpdated) {
493 const uint32_t kCumLost1 = 1;
494 const uint32_t kExtSeqNum1 = 10;
495 const uint32_t kCumLost2 = 2;
496 const uint32_t kExtSeqNum2 = 20;
497
498 // One report block received.
499 RtcpStatistics rtcp_stats1;
srte186d9c32017-08-04 05:03:53 -0700500 rtcp_stats1.packets_lost = kCumLost1;
501 rtcp_stats1.extended_highest_sequence_number = kExtSeqNum1;
asapersson0c43f772016-11-30 01:42:26 -0800502 statistics_proxy_->StatisticsUpdated(rtcp_stats1, kRemoteSsrc);
503
504 // Two report blocks received.
505 RtcpStatistics rtcp_stats2;
srte186d9c32017-08-04 05:03:53 -0700506 rtcp_stats2.packets_lost = kCumLost2;
507 rtcp_stats2.extended_highest_sequence_number = kExtSeqNum2;
asapersson0c43f772016-11-30 01:42:26 -0800508 statistics_proxy_->StatisticsUpdated(rtcp_stats2, kRemoteSsrc);
509
510 // Two received report blocks but min run time has not passed.
511 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
512 SetUp(); // Reset stat proxy causes histograms to be updated.
513 EXPECT_EQ(0,
514 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
515
516 // Two report blocks received.
517 statistics_proxy_->StatisticsUpdated(rtcp_stats1, kRemoteSsrc);
518 statistics_proxy_->StatisticsUpdated(rtcp_stats2, kRemoteSsrc);
519
520 // Two received report blocks and min run time has passed.
521 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
522 SetUp();
523 EXPECT_EQ(1,
524 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
525 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.ReceivedPacketsLostInPercent",
526 (kCumLost2 - kCumLost1) * 100 /
527 (kExtSeqNum2 - kExtSeqNum1)));
528}
529
530TEST_F(ReceiveStatisticsProxyTest,
531 PacketLossHistogramIsNotUpdatedIfLessThanTwoReportBlocksAreReceived) {
532 RtcpStatistics rtcp_stats1;
srte186d9c32017-08-04 05:03:53 -0700533 rtcp_stats1.packets_lost = 1;
534 rtcp_stats1.extended_highest_sequence_number = 10;
asapersson0c43f772016-11-30 01:42:26 -0800535
536 // Min run time has passed but no received report block.
537 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
538 SetUp(); // Reset stat proxy causes histograms to be updated.
539 EXPECT_EQ(0,
540 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
541
542 // Min run time has passed but only one received report block.
543 statistics_proxy_->StatisticsUpdated(rtcp_stats1, kRemoteSsrc);
544 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
545 SetUp();
546 EXPECT_EQ(0,
547 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
548}
549
asapersson2077f2f2017-05-11 05:37:35 -0700550TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsAvSyncOffset) {
551 const int64_t kSyncOffsetMs = 22;
552 const double kFreqKhz = 90.0;
553 EXPECT_EQ(std::numeric_limits<int>::max(),
554 statistics_proxy_->GetStats().sync_offset_ms);
555 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
556 EXPECT_EQ(kSyncOffsetMs, statistics_proxy_->GetStats().sync_offset_ms);
557}
558
asapersson46c4e3c2016-11-03 06:48:19 -0700559TEST_F(ReceiveStatisticsProxyTest, AvSyncOffsetHistogramIsUpdated) {
560 const int64_t kSyncOffsetMs = 22;
561 const double kFreqKhz = 90.0;
562 for (int i = 0; i < kMinRequiredSamples; ++i)
563 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
564 // Histograms are updated when the statistics_proxy_ is deleted.
565 statistics_proxy_.reset();
566 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AVSyncOffsetInMs"));
567 EXPECT_EQ(1,
568 metrics::NumEvents("WebRTC.Video.AVSyncOffsetInMs", kSyncOffsetMs));
569}
570
asaperssonde9e5ff2016-11-02 07:14:03 -0700571TEST_F(ReceiveStatisticsProxyTest, RtpToNtpFrequencyOffsetHistogramIsUpdated) {
572 const int64_t kSyncOffsetMs = 22;
573 const double kFreqKhz = 90.0;
574 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
575 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz + 2.2);
576 fake_clock_.AdvanceTimeMilliseconds(kFreqOffsetProcessIntervalInMs);
577 // Process interval passed, max diff: 2.
578 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz + 1.1);
579 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz - 4.2);
580 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz - 0.9);
581 fake_clock_.AdvanceTimeMilliseconds(kFreqOffsetProcessIntervalInMs);
582 // Process interval passed, max diff: 4.
583 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
584 statistics_proxy_.reset();
585 // Average reported: (2 + 4) / 2 = 3.
586 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtpToNtpFreqOffsetInKhz"));
587 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtpToNtpFreqOffsetInKhz", 3));
588}
589
asapersson6966bd52017-01-03 00:44:06 -0800590TEST_F(ReceiveStatisticsProxyTest, Vp8QpHistogramIsUpdated) {
591 const int kQp = 22;
asapersson6966bd52017-01-03 00:44:06 -0800592
593 for (int i = 0; i < kMinRequiredSamples; ++i)
Niels Möller147013a2018-10-01 15:56:33 +0200594 statistics_proxy_->OnPreDecode(kVideoCodecVP8, kQp);
asapersson6966bd52017-01-03 00:44:06 -0800595
596 statistics_proxy_.reset();
597 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
598 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Decoded.Vp8.Qp", kQp));
599}
600
601TEST_F(ReceiveStatisticsProxyTest, Vp8QpHistogramIsNotUpdatedForTooFewSamples) {
Niels Möller147013a2018-10-01 15:56:33 +0200602 const int kQp = 22;
asapersson6966bd52017-01-03 00:44:06 -0800603
604 for (int i = 0; i < kMinRequiredSamples - 1; ++i)
Niels Möller147013a2018-10-01 15:56:33 +0200605 statistics_proxy_->OnPreDecode(kVideoCodecVP8, kQp);
asapersson6966bd52017-01-03 00:44:06 -0800606
607 statistics_proxy_.reset();
608 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
609}
610
611TEST_F(ReceiveStatisticsProxyTest, Vp8QpHistogramIsNotUpdatedIfNoQpValue) {
asapersson6966bd52017-01-03 00:44:06 -0800612 for (int i = 0; i < kMinRequiredSamples; ++i)
Niels Möller147013a2018-10-01 15:56:33 +0200613 statistics_proxy_->OnPreDecode(kVideoCodecVP8, -1);
asapersson6966bd52017-01-03 00:44:06 -0800614
615 statistics_proxy_.reset();
616 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
617}
618
asaperssonb99baf82017-04-20 04:05:43 -0700619TEST_F(ReceiveStatisticsProxyTest,
620 KeyFrameHistogramNotUpdatedForTooFewSamples) {
621 const bool kIsKeyFrame = false;
622 const int kFrameSizeBytes = 1000;
623
624 for (int i = 0; i < kMinRequiredSamples - 1; ++i)
ilnik6d5b4d62017-08-30 03:32:14 -0700625 statistics_proxy_->OnCompleteFrame(kIsKeyFrame, kFrameSizeBytes,
626 VideoContentType::UNSPECIFIED);
asaperssonb99baf82017-04-20 04:05:43 -0700627
628 EXPECT_EQ(0, statistics_proxy_->GetStats().frame_counts.key_frames);
629 EXPECT_EQ(kMinRequiredSamples - 1,
630 statistics_proxy_->GetStats().frame_counts.delta_frames);
631
632 statistics_proxy_.reset();
633 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
634}
635
636TEST_F(ReceiveStatisticsProxyTest,
637 KeyFrameHistogramUpdatedForMinRequiredSamples) {
638 const bool kIsKeyFrame = false;
639 const int kFrameSizeBytes = 1000;
640
641 for (int i = 0; i < kMinRequiredSamples; ++i)
ilnik6d5b4d62017-08-30 03:32:14 -0700642 statistics_proxy_->OnCompleteFrame(kIsKeyFrame, kFrameSizeBytes,
643 VideoContentType::UNSPECIFIED);
asaperssonb99baf82017-04-20 04:05:43 -0700644
645 EXPECT_EQ(0, statistics_proxy_->GetStats().frame_counts.key_frames);
646 EXPECT_EQ(kMinRequiredSamples,
647 statistics_proxy_->GetStats().frame_counts.delta_frames);
648
649 statistics_proxy_.reset();
650 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
651 EXPECT_EQ(1,
652 metrics::NumEvents("WebRTC.Video.KeyFramesReceivedInPermille", 0));
653}
654
655TEST_F(ReceiveStatisticsProxyTest, KeyFrameHistogramIsUpdated) {
656 const int kFrameSizeBytes = 1000;
657
658 for (int i = 0; i < kMinRequiredSamples; ++i)
ilnik6d5b4d62017-08-30 03:32:14 -0700659 statistics_proxy_->OnCompleteFrame(true, kFrameSizeBytes,
660 VideoContentType::UNSPECIFIED);
asaperssonb99baf82017-04-20 04:05:43 -0700661
662 for (int i = 0; i < kMinRequiredSamples; ++i)
ilnik6d5b4d62017-08-30 03:32:14 -0700663 statistics_proxy_->OnCompleteFrame(false, kFrameSizeBytes,
664 VideoContentType::UNSPECIFIED);
asaperssonb99baf82017-04-20 04:05:43 -0700665
666 EXPECT_EQ(kMinRequiredSamples,
667 statistics_proxy_->GetStats().frame_counts.key_frames);
668 EXPECT_EQ(kMinRequiredSamples,
669 statistics_proxy_->GetStats().frame_counts.delta_frames);
670
671 statistics_proxy_.reset();
672 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
673 EXPECT_EQ(
674 1, metrics::NumEvents("WebRTC.Video.KeyFramesReceivedInPermille", 500));
675}
676
677TEST_F(ReceiveStatisticsProxyTest, TimingHistogramsNotUpdatedForTooFewSamples) {
678 const int kDecodeMs = 1;
679 const int kMaxDecodeMs = 2;
680 const int kCurrentDelayMs = 3;
681 const int kTargetDelayMs = 4;
682 const int kJitterBufferMs = 5;
683 const int kMinPlayoutDelayMs = 6;
684 const int kRenderDelayMs = 7;
685
686 for (int i = 0; i < kMinRequiredSamples - 1; ++i) {
687 statistics_proxy_->OnFrameBufferTimingsUpdated(
688 kDecodeMs, kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs,
689 kJitterBufferMs, kMinPlayoutDelayMs, kRenderDelayMs);
690 }
691
692 statistics_proxy_.reset();
693 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
694 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
695 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
696 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
697 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
698}
699
700TEST_F(ReceiveStatisticsProxyTest, TimingHistogramsAreUpdated) {
701 const int kDecodeMs = 1;
702 const int kMaxDecodeMs = 2;
703 const int kCurrentDelayMs = 3;
704 const int kTargetDelayMs = 4;
705 const int kJitterBufferMs = 5;
706 const int kMinPlayoutDelayMs = 6;
707 const int kRenderDelayMs = 7;
708
709 for (int i = 0; i < kMinRequiredSamples; ++i) {
710 statistics_proxy_->OnFrameBufferTimingsUpdated(
711 kDecodeMs, kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs,
712 kJitterBufferMs, kMinPlayoutDelayMs, kRenderDelayMs);
713 }
714
715 statistics_proxy_.reset();
716 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
717 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
718 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
719 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
720 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
721
722 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DecodeTimeInMs", kDecodeMs));
723 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.JitterBufferDelayInMs",
724 kJitterBufferMs));
725 EXPECT_EQ(1,
726 metrics::NumEvents("WebRTC.Video.TargetDelayInMs", kTargetDelayMs));
727 EXPECT_EQ(
728 1, metrics::NumEvents("WebRTC.Video.CurrentDelayInMs", kCurrentDelayMs));
729 EXPECT_EQ(1,
730 metrics::NumEvents("WebRTC.Video.OnewayDelayInMs", kTargetDelayMs));
731}
732
sprang948b2752017-05-04 02:47:13 -0700733TEST_F(ReceiveStatisticsProxyTest, DoesNotReportStaleFramerates) {
734 const int kDefaultFps = 30;
sprang948b2752017-05-04 02:47:13 -0700735 rtc::scoped_refptr<VideoFrameBuffer> video_frame_buffer(
736 I420Buffer::Create(kWidth, kHeight));
Artem Titov1ebfb6a2019-01-03 23:49:37 +0100737 VideoFrame frame = VideoFrame::Builder()
738 .set_video_frame_buffer(video_frame_buffer)
739 .set_rotation(webrtc::kVideoRotation_0)
740 .set_timestamp_us(0)
741 .build();
sprang948b2752017-05-04 02:47:13 -0700742
743 for (int i = 0; i < kDefaultFps; ++i) {
744 // Since OnRenderedFrame is never called the fps in each sample will be 0,
745 // i.e. bad
746 frame.set_ntp_time_ms(fake_clock_.CurrentNtpInMilliseconds());
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200747 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
sprang948b2752017-05-04 02:47:13 -0700748 VideoContentType::UNSPECIFIED);
749 statistics_proxy_->OnRenderedFrame(frame);
750 fake_clock_.AdvanceTimeMilliseconds(1000 / kDefaultFps);
751 }
752
753 EXPECT_EQ(kDefaultFps, statistics_proxy_->GetStats().decode_frame_rate);
754 EXPECT_EQ(kDefaultFps, statistics_proxy_->GetStats().render_frame_rate);
755
756 // FPS trackers in stats proxy have a 1000ms sliding window.
757 fake_clock_.AdvanceTimeMilliseconds(1000);
758 EXPECT_EQ(0, statistics_proxy_->GetStats().decode_frame_rate);
759 EXPECT_EQ(0, statistics_proxy_->GetStats().render_frame_rate);
760}
761
asapersson2077f2f2017-05-11 05:37:35 -0700762TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsReceivedFrameStats) {
asapersson2077f2f2017-05-11 05:37:35 -0700763 EXPECT_EQ(0, statistics_proxy_->GetStats().width);
764 EXPECT_EQ(0, statistics_proxy_->GetStats().height);
765 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_rendered);
766
767 statistics_proxy_->OnRenderedFrame(CreateFrame(kWidth, kHeight));
768
769 EXPECT_EQ(kWidth, statistics_proxy_->GetStats().width);
770 EXPECT_EQ(kHeight, statistics_proxy_->GetStats().height);
771 EXPECT_EQ(1u, statistics_proxy_->GetStats().frames_rendered);
772}
773
774TEST_F(ReceiveStatisticsProxyTest,
775 ReceivedFrameHistogramsAreNotUpdatedForTooFewSamples) {
asapersson2077f2f2017-05-11 05:37:35 -0700776 for (int i = 0; i < kMinRequiredSamples - 1; ++i)
777 statistics_proxy_->OnRenderedFrame(CreateFrame(kWidth, kHeight));
778
779 statistics_proxy_.reset();
780 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
781 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
782 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
783 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
784}
785
786TEST_F(ReceiveStatisticsProxyTest, ReceivedFrameHistogramsAreUpdated) {
asapersson2077f2f2017-05-11 05:37:35 -0700787 for (int i = 0; i < kMinRequiredSamples; ++i)
788 statistics_proxy_->OnRenderedFrame(CreateFrame(kWidth, kHeight));
789
790 statistics_proxy_.reset();
791 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
792 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
793 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
794 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
795 EXPECT_EQ(1,
796 metrics::NumEvents("WebRTC.Video.ReceivedWidthInPixels", kWidth));
797 EXPECT_EQ(1,
798 metrics::NumEvents("WebRTC.Video.ReceivedHeightInPixels", kHeight));
799}
800
Åsa Persson81327d52018-06-05 13:34:33 +0200801TEST_F(ReceiveStatisticsProxyTest, ZeroDelayReportedIfFrameNotDelayed) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200802 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Åsa Persson81327d52018-06-05 13:34:33 +0200803 VideoContentType::UNSPECIFIED);
804
805 // Frame not delayed, delayed frames to render: 0%.
806 const int64_t kNowMs = fake_clock_.TimeInMilliseconds();
807 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs));
808
809 // Min run time has passed.
810 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000));
811 statistics_proxy_.reset();
812 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
813 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer", 0));
814 EXPECT_EQ(0, metrics::NumSamples(
815 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
816}
817
818TEST_F(ReceiveStatisticsProxyTest,
819 DelayedFrameHistogramsAreNotUpdatedIfMinRuntimeHasNotPassed) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200820 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Åsa Persson81327d52018-06-05 13:34:33 +0200821 VideoContentType::UNSPECIFIED);
822
823 // Frame not delayed, delayed frames to render: 0%.
824 const int64_t kNowMs = fake_clock_.TimeInMilliseconds();
825 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs));
826
827 // Min run time has not passed.
828 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000) -
829 1);
830 statistics_proxy_.reset();
831 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
832 EXPECT_EQ(0, metrics::NumSamples(
833 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
834}
835
836TEST_F(ReceiveStatisticsProxyTest,
837 DelayedFramesHistogramsAreNotUpdatedIfNoRenderedFrames) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200838 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Åsa Persson81327d52018-06-05 13:34:33 +0200839 VideoContentType::UNSPECIFIED);
840
841 // Min run time has passed. No rendered frames.
842 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000));
843 statistics_proxy_.reset();
844 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
845 EXPECT_EQ(0, metrics::NumSamples(
846 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
847}
848
849TEST_F(ReceiveStatisticsProxyTest, DelayReportedIfFrameIsDelayed) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200850 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Åsa Persson81327d52018-06-05 13:34:33 +0200851 VideoContentType::UNSPECIFIED);
852
853 // Frame delayed 1 ms, delayed frames to render: 100%.
854 const int64_t kNowMs = fake_clock_.TimeInMilliseconds();
855 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs - 1));
856
857 // Min run time has passed.
858 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000));
859 statistics_proxy_.reset();
860 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
861 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer", 100));
862 EXPECT_EQ(1, metrics::NumSamples(
863 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
864 EXPECT_EQ(1, metrics::NumEvents(
865 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs", 1));
866}
867
868TEST_F(ReceiveStatisticsProxyTest, AverageDelayOfDelayedFramesIsReported) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200869 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Åsa Persson81327d52018-06-05 13:34:33 +0200870 VideoContentType::UNSPECIFIED);
871
872 // Two frames delayed (6 ms, 10 ms), delayed frames to render: 50%.
873 const int64_t kNowMs = fake_clock_.TimeInMilliseconds();
874 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs - 10));
875 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs - 6));
876 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs));
877 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs + 1));
878
879 // Min run time has passed.
880 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000));
881 statistics_proxy_.reset();
882 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
883 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer", 50));
884 EXPECT_EQ(1, metrics::NumSamples(
885 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
886 EXPECT_EQ(1, metrics::NumEvents(
887 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs", 8));
888}
889
asapersson2077f2f2017-05-11 05:37:35 -0700890TEST_F(ReceiveStatisticsProxyTest,
891 RtcpHistogramsNotUpdatedIfMinRuntimeHasNotPassed) {
892 InsertFirstRtpPacket(kRemoteSsrc);
893 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000) -
894 1);
895
896 RtcpPacketTypeCounter counter;
897 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc, counter);
898
899 statistics_proxy_.reset();
900 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
901 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
902 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
903}
904
905TEST_F(ReceiveStatisticsProxyTest, RtcpHistogramsAreUpdated) {
906 InsertFirstRtpPacket(kRemoteSsrc);
907 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
908
909 const uint32_t kFirPackets = 100;
910 const uint32_t kPliPackets = 200;
911 const uint32_t kNackPackets = 300;
912
913 RtcpPacketTypeCounter counter;
914 counter.fir_packets = kFirPackets;
915 counter.pli_packets = kPliPackets;
916 counter.nack_packets = kNackPackets;
917 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc, counter);
918
919 statistics_proxy_.reset();
920 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
921 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
922 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
923 EXPECT_EQ(
924 1, metrics::NumEvents("WebRTC.Video.FirPacketsSentPerMinute",
925 kFirPackets * 60 / metrics::kMinRunTimeInSeconds));
926 EXPECT_EQ(
927 1, metrics::NumEvents("WebRTC.Video.PliPacketsSentPerMinute",
928 kPliPackets * 60 / metrics::kMinRunTimeInSeconds));
929 EXPECT_EQ(
930 1, metrics::NumEvents("WebRTC.Video.NackPacketsSentPerMinute",
931 kNackPackets * 60 / metrics::kMinRunTimeInSeconds));
932}
933
sprang892dab52017-08-15 05:00:33 -0700934INSTANTIATE_TEST_CASE_P(ContentTypes,
935 ReceiveStatisticsProxyTest,
936 ::testing::Values(VideoContentType::UNSPECIFIED,
937 VideoContentType::SCREENSHARE));
938
939TEST_P(ReceiveStatisticsProxyTest, InterFrameDelaysAreReported) {
940 const VideoContentType content_type = GetParam();
941 const int kInterFrameDelayMs = 33;
942 for (int i = 0; i < kMinRequiredSamples; ++i) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200943 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200944 content_type);
sprang892dab52017-08-15 05:00:33 -0700945 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
946 }
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +0200947 // One extra with double the interval.
sprang892dab52017-08-15 05:00:33 -0700948 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200949 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200950 content_type);
sprang892dab52017-08-15 05:00:33 -0700951
952 statistics_proxy_.reset();
953 const int kExpectedInterFrame =
954 (kInterFrameDelayMs * (kMinRequiredSamples - 1) +
955 kInterFrameDelayMs * 2) /
956 kMinRequiredSamples;
ilnik6d5b4d62017-08-30 03:32:14 -0700957 if (videocontenttypehelpers::IsScreenshare(content_type)) {
958 EXPECT_EQ(
959 kExpectedInterFrame,
960 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs"));
961 EXPECT_EQ(
962 kInterFrameDelayMs * 2,
963 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
964 } else {
965 EXPECT_EQ(kExpectedInterFrame,
966 metrics::MinSample("WebRTC.Video.InterframeDelayInMs"));
967 EXPECT_EQ(kInterFrameDelayMs * 2,
968 metrics::MinSample("WebRTC.Video.InterframeDelayMaxInMs"));
sprang892dab52017-08-15 05:00:33 -0700969 }
970}
971
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +0200972TEST_P(ReceiveStatisticsProxyTest, InterFrameDelaysPercentilesAreReported) {
973 const VideoContentType content_type = GetParam();
974 const int kInterFrameDelayMs = 33;
975 const int kLastFivePercentsSamples = kMinRequiredSamples * 5 / 100;
976 for (int i = 0; i <= kMinRequiredSamples - kLastFivePercentsSamples; ++i) {
977 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200978 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200979 content_type);
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +0200980 }
981 // Last 5% of intervals are double in size.
982 for (int i = 0; i < kLastFivePercentsSamples; ++i) {
983 fake_clock_.AdvanceTimeMilliseconds(2 * kInterFrameDelayMs);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200984 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200985 content_type);
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +0200986 }
987 // Final sample is outlier and 10 times as big.
988 fake_clock_.AdvanceTimeMilliseconds(10 * kInterFrameDelayMs);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200989 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200990 content_type);
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +0200991
992 statistics_proxy_.reset();
993 const int kExpectedInterFrame = kInterFrameDelayMs * 2;
994 if (videocontenttypehelpers::IsScreenshare(content_type)) {
995 EXPECT_EQ(kExpectedInterFrame,
996 metrics::MinSample(
997 "WebRTC.Video.Screenshare.InterframeDelay95PercentileInMs"));
998 } else {
999 EXPECT_EQ(
1000 kExpectedInterFrame,
1001 metrics::MinSample("WebRTC.Video.InterframeDelay95PercentileInMs"));
1002 }
1003}
1004
sprang892dab52017-08-15 05:00:33 -07001005TEST_P(ReceiveStatisticsProxyTest, MaxInterFrameDelayOnlyWithValidAverage) {
1006 const VideoContentType content_type = GetParam();
1007 const int kInterFrameDelayMs = 33;
1008 for (int i = 0; i < kMinRequiredSamples; ++i) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +02001009 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001010 content_type);
sprang892dab52017-08-15 05:00:33 -07001011 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1012 }
1013
1014 // |kMinRequiredSamples| samples, and thereby intervals, is required. That
1015 // means we're one frame short of having a valid data set.
1016 statistics_proxy_.reset();
1017 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
1018 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
1019 EXPECT_EQ(
1020 0, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1021 EXPECT_EQ(0, metrics::NumSamples(
1022 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1023}
1024
sprang3e86e7e2017-08-22 09:23:28 -07001025TEST_P(ReceiveStatisticsProxyTest, MaxInterFrameDelayOnlyWithPause) {
1026 const VideoContentType content_type = GetParam();
1027 const int kInterFrameDelayMs = 33;
1028 for (int i = 0; i <= kMinRequiredSamples; ++i) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +02001029 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001030 content_type);
sprang3e86e7e2017-08-22 09:23:28 -07001031 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1032 }
1033
1034 // At this state, we should have a valid inter-frame delay.
1035 // Indicate stream paused and make a large jump in time.
1036 statistics_proxy_->OnStreamInactive();
1037 fake_clock_.AdvanceTimeMilliseconds(5000);
1038
1039 // Insert two more frames. The interval during the pause should be disregarded
1040 // in the stats.
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 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +02001044 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001045 content_type);
sprang3e86e7e2017-08-22 09:23:28 -07001046
1047 statistics_proxy_.reset();
ilnik6d5b4d62017-08-30 03:32:14 -07001048 if (videocontenttypehelpers::IsScreenshare(content_type)) {
sprang3e86e7e2017-08-22 09:23:28 -07001049 EXPECT_EQ(
1050 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1051 EXPECT_EQ(1, metrics::NumSamples(
1052 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1053 EXPECT_EQ(
1054 kInterFrameDelayMs,
1055 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1056 EXPECT_EQ(
1057 kInterFrameDelayMs,
1058 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1059 } else {
1060 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
1061 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
1062 EXPECT_EQ(kInterFrameDelayMs,
1063 metrics::MinSample("WebRTC.Video.InterframeDelayInMs"));
1064 EXPECT_EQ(kInterFrameDelayMs,
1065 metrics::MinSample("WebRTC.Video.InterframeDelayMaxInMs"));
1066 }
1067}
1068
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001069TEST_P(ReceiveStatisticsProxyTest, FreezesAreReported) {
1070 const VideoContentType content_type = GetParam();
1071 const int kInterFrameDelayMs = 33;
1072 const int kFreezeDelayMs = 200;
Sergey Silkinbea18ca2018-10-02 16:22:46 +02001073 const int kCallDurationMs =
1074 kMinRequiredSamples * kInterFrameDelayMs + kFreezeDelayMs;
Artem Titov1ebfb6a2019-01-03 23:49:37 +01001075 webrtc::VideoFrame frame =
1076 VideoFrame::Builder()
1077 .set_video_frame_buffer(webrtc::I420Buffer::Create(1, 1))
1078 .set_timestamp_rtp(0)
1079 .set_timestamp_us(0)
1080 .set_rotation(kVideoRotation_0)
1081 .build();
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001082 for (int i = 0; i < kMinRequiredSamples; ++i) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +02001083 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001084 content_type);
Ilya Nikolaevskiycdc959f2018-10-10 13:15:09 +02001085 statistics_proxy_->OnRenderedFrame(frame);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001086 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1087 }
1088 // Add extra freeze.
1089 fake_clock_.AdvanceTimeMilliseconds(kFreezeDelayMs);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +02001090 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001091 content_type);
Ilya Nikolaevskiycdc959f2018-10-10 13:15:09 +02001092 statistics_proxy_->OnRenderedFrame(frame);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001093
1094 statistics_proxy_.reset();
1095 const int kExpectedTimeBetweenFreezes =
1096 kInterFrameDelayMs * (kMinRequiredSamples - 1);
Sergey Silkinbea18ca2018-10-02 16:22:46 +02001097 const int kExpectedNumberFreezesPerMinute = 60 * 1000 / kCallDurationMs;
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001098 if (videocontenttypehelpers::IsScreenshare(content_type)) {
1099 EXPECT_EQ(
1100 kFreezeDelayMs + kInterFrameDelayMs,
1101 metrics::MinSample("WebRTC.Video.Screenshare.MeanFreezeDurationMs"));
1102 EXPECT_EQ(kExpectedTimeBetweenFreezes,
1103 metrics::MinSample(
1104 "WebRTC.Video.Screenshare.MeanTimeBetweenFreezesMs"));
Sergey Silkinbea18ca2018-10-02 16:22:46 +02001105 EXPECT_EQ(
1106 kExpectedNumberFreezesPerMinute,
1107 metrics::MinSample("WebRTC.Video.Screenshare.NumberFreezesPerMinute"));
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001108 } else {
1109 EXPECT_EQ(kFreezeDelayMs + kInterFrameDelayMs,
1110 metrics::MinSample("WebRTC.Video.MeanFreezeDurationMs"));
1111 EXPECT_EQ(kExpectedTimeBetweenFreezes,
1112 metrics::MinSample("WebRTC.Video.MeanTimeBetweenFreezesMs"));
Sergey Silkinbea18ca2018-10-02 16:22:46 +02001113 EXPECT_EQ(kExpectedNumberFreezesPerMinute,
1114 metrics::MinSample("WebRTC.Video.NumberFreezesPerMinute"));
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001115 }
1116}
1117
1118TEST_P(ReceiveStatisticsProxyTest, PausesAreIgnored) {
1119 const VideoContentType content_type = GetParam();
1120 const int kInterFrameDelayMs = 33;
1121 const int kPauseDurationMs = 10000;
Artem Titov1ebfb6a2019-01-03 23:49:37 +01001122 webrtc::VideoFrame frame =
1123 VideoFrame::Builder()
1124 .set_video_frame_buffer(webrtc::I420Buffer::Create(1, 1))
1125 .set_timestamp_rtp(0)
1126 .set_timestamp_us(0)
1127 .set_rotation(kVideoRotation_0)
1128 .build();
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001129 for (int i = 0; i <= kMinRequiredSamples; ++i) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +02001130 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001131 content_type);
Ilya Nikolaevskiycdc959f2018-10-10 13:15:09 +02001132 statistics_proxy_->OnRenderedFrame(frame);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001133 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1134 }
1135 // Add a pause.
1136 fake_clock_.AdvanceTimeMilliseconds(kPauseDurationMs);
1137 statistics_proxy_->OnStreamInactive();
1138
1139 // Second playback interval with triple the length.
1140 for (int i = 0; i <= kMinRequiredSamples * 3; ++i) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +02001141 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001142 content_type);
Ilya Nikolaevskiycdc959f2018-10-10 13:15:09 +02001143 statistics_proxy_->OnRenderedFrame(frame);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001144 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1145 }
1146
1147 statistics_proxy_.reset();
1148 // Average of two playback intervals.
1149 const int kExpectedTimeBetweenFreezes =
1150 kInterFrameDelayMs * kMinRequiredSamples * 2;
1151 if (videocontenttypehelpers::IsScreenshare(content_type)) {
1152 EXPECT_EQ(-1, metrics::MinSample(
1153 "WebRTC.Video.Screenshare.MeanFreezeDurationMs"));
1154 EXPECT_EQ(kExpectedTimeBetweenFreezes,
1155 metrics::MinSample(
1156 "WebRTC.Video.Screenshare.MeanTimeBetweenFreezesMs"));
1157 } else {
1158 EXPECT_EQ(-1, metrics::MinSample("WebRTC.Video.MeanFreezeDurationMs"));
1159 EXPECT_EQ(kExpectedTimeBetweenFreezes,
1160 metrics::MinSample("WebRTC.Video.MeanTimeBetweenFreezesMs"));
1161 }
1162}
1163
Ilya Nikolaevskiy879f5a32018-05-31 09:47:17 +02001164TEST_P(ReceiveStatisticsProxyTest, ManyPausesAtTheBeginning) {
1165 const VideoContentType content_type = GetParam();
1166 const int kInterFrameDelayMs = 33;
1167 const int kPauseDurationMs = 10000;
1168 for (int i = 0; i <= kMinRequiredSamples; ++i) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +02001169 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy879f5a32018-05-31 09:47:17 +02001170 content_type);
1171 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1172
1173 statistics_proxy_->OnStreamInactive();
1174 fake_clock_.AdvanceTimeMilliseconds(kPauseDurationMs);
1175
Danil Chapovalovb9b146c2018-06-15 12:28:07 +02001176 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
1177 content_type);
Ilya Nikolaevskiy879f5a32018-05-31 09:47:17 +02001178 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1179 }
1180
1181 statistics_proxy_.reset();
1182 // No freezes should be detected, as all long inter-frame delays were pauses.
1183 if (videocontenttypehelpers::IsScreenshare(content_type)) {
1184 EXPECT_EQ(-1, metrics::MinSample(
1185 "WebRTC.Video.Screenshare.MeanFreezeDurationMs"));
1186 } else {
1187 EXPECT_EQ(-1, metrics::MinSample("WebRTC.Video.MeanFreezeDurationMs"));
1188 }
1189}
1190
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001191TEST_P(ReceiveStatisticsProxyTest, TimeInHdReported) {
1192 const VideoContentType content_type = GetParam();
1193 const int kInterFrameDelayMs = 20;
1194 // HD frames.
1195 for (int i = 0; i < kMinRequiredSamples; ++i) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +02001196 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001197 content_type);
1198 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1199 }
1200 // SD frames.
1201 for (int i = 0; i < 2 * kMinRequiredSamples; ++i) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +02001202 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth / 2, kHeight / 2,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001203 content_type);
1204 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1205 }
1206 // Extra last frame.
Danil Chapovalovb9b146c2018-06-15 12:28:07 +02001207 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth / 2, kHeight / 2,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001208 content_type);
1209 statistics_proxy_.reset();
1210 const int kExpectedTimeInHdPercents = 33;
1211 if (videocontenttypehelpers::IsScreenshare(content_type)) {
1212 EXPECT_EQ(
1213 kExpectedTimeInHdPercents,
1214 metrics::MinSample("WebRTC.Video.Screenshare.TimeInHdPercentage"));
1215 } else {
1216 EXPECT_EQ(kExpectedTimeInHdPercents,
1217 metrics::MinSample("WebRTC.Video.TimeInHdPercentage"));
1218 }
1219}
1220
1221TEST_P(ReceiveStatisticsProxyTest, TimeInBlockyVideoReported) {
1222 const VideoContentType content_type = GetParam();
1223 const int kInterFrameDelayMs = 20;
1224 const int kHighQp = 80;
1225 const int kLowQp = 30;
1226 // High quality frames.
1227 for (int i = 0; i < kMinRequiredSamples; ++i) {
1228 statistics_proxy_->OnDecodedFrame(kLowQp, kWidth, kHeight, content_type);
1229 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1230 }
1231 // Blocky frames.
1232 for (int i = 0; i < 2 * kMinRequiredSamples; ++i) {
1233 statistics_proxy_->OnDecodedFrame(kHighQp, kWidth, kHeight, content_type);
1234 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1235 }
1236 // Extra last frame.
1237 statistics_proxy_->OnDecodedFrame(kHighQp, kWidth, kHeight, content_type);
1238 statistics_proxy_.reset();
1239 const int kExpectedTimeInHdPercents = 66;
1240 if (videocontenttypehelpers::IsScreenshare(content_type)) {
1241 EXPECT_EQ(kExpectedTimeInHdPercents,
1242 metrics::MinSample(
1243 "WebRTC.Video.Screenshare.TimeInBlockyVideoPercentage"));
1244 } else {
1245 EXPECT_EQ(kExpectedTimeInHdPercents,
1246 metrics::MinSample("WebRTC.Video.TimeInBlockyVideoPercentage"));
1247 }
1248}
1249
1250TEST_P(ReceiveStatisticsProxyTest, DownscalesReported) {
1251 const VideoContentType content_type = GetParam();
1252 const int kInterFrameDelayMs = 1000; // To ensure long enough call duration.
1253 const int kLowQp = 30;
1254
1255 statistics_proxy_->OnDecodedFrame(kLowQp, kWidth / 2, kHeight / 2,
1256 content_type);
1257 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1258
1259 // Downscale.
1260 statistics_proxy_->OnDecodedFrame(kLowQp, kWidth, kHeight, content_type);
1261 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1262
1263 statistics_proxy_->OnDecodedFrame(kLowQp, kWidth / 2, kHeight / 2,
1264 content_type);
1265 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1266
1267 statistics_proxy_->OnDecodedFrame(kLowQp, kWidth / 2, kHeight / 2,
1268 content_type);
1269 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1270
1271 // Downscale.
1272 statistics_proxy_->OnDecodedFrame(kLowQp, kWidth / 4, kHeight / 4,
1273 content_type);
1274 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1275
1276 statistics_proxy_.reset();
1277 const int kExpectedDownscales = 30; // 2 per 5 seconds = 30 per minute.
1278 if (videocontenttypehelpers::IsScreenshare(content_type)) {
1279 EXPECT_EQ(
1280 kExpectedDownscales,
1281 metrics::MinSample(
1282 "WebRTC.Video.Screenshare.NumberResolutionDownswitchesPerMinute"));
1283 } else {
1284 EXPECT_EQ(kExpectedDownscales,
1285 metrics::MinSample(
1286 "WebRTC.Video.NumberResolutionDownswitchesPerMinute"));
1287 }
1288}
1289
ilnik6d5b4d62017-08-30 03:32:14 -07001290TEST_P(ReceiveStatisticsProxyTest, StatsAreSlicedOnSimulcastAndExperiment) {
1291 VideoContentType content_type = GetParam();
1292 const uint8_t experiment_id = 1;
1293 videocontenttypehelpers::SetExperimentId(&content_type, experiment_id);
1294 const int kInterFrameDelayMs1 = 30;
1295 const int kInterFrameDelayMs2 = 50;
1296
1297 videocontenttypehelpers::SetSimulcastId(&content_type, 1);
1298 for (int i = 0; i <= kMinRequiredSamples; ++i) {
1299 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs1);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +02001300 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001301 content_type);
ilnik6d5b4d62017-08-30 03:32:14 -07001302 }
1303
1304 videocontenttypehelpers::SetSimulcastId(&content_type, 2);
1305 for (int i = 0; i <= kMinRequiredSamples; ++i) {
1306 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs2);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +02001307 statistics_proxy_->OnDecodedFrame(absl::nullopt, kWidth, kHeight,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001308 content_type);
ilnik6d5b4d62017-08-30 03:32:14 -07001309 }
1310 statistics_proxy_.reset();
1311
1312 if (videocontenttypehelpers::IsScreenshare(content_type)) {
1313 EXPECT_EQ(
1314 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1315 EXPECT_EQ(1, metrics::NumSamples(
1316 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1317 EXPECT_EQ(1, metrics::NumSamples(
1318 "WebRTC.Video.Screenshare.InterframeDelayInMs.S0"));
1319 EXPECT_EQ(1, metrics::NumSamples(
1320 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs.S0"));
1321 EXPECT_EQ(1, metrics::NumSamples(
1322 "WebRTC.Video.Screenshare.InterframeDelayInMs.S1"));
1323 EXPECT_EQ(1, metrics::NumSamples(
1324 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs.S1"));
1325 EXPECT_EQ(1,
1326 metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"
1327 ".ExperimentGroup0"));
1328 EXPECT_EQ(
1329 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"
1330 ".ExperimentGroup0"));
1331 EXPECT_EQ(
1332 kInterFrameDelayMs1,
1333 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs.S0"));
1334 EXPECT_EQ(
1335 kInterFrameDelayMs2,
1336 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs.S1"));
1337 EXPECT_EQ(
1338 (kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1339 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1340 EXPECT_EQ(
1341 kInterFrameDelayMs2,
1342 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1343 EXPECT_EQ(
1344 (kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1345 metrics::MinSample(
1346 "WebRTC.Video.Screenshare.InterframeDelayInMs.ExperimentGroup0"));
1347 } else {
1348 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
1349 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
1350 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs.S0"));
1351 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs.S0"));
1352 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs.S1"));
1353 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs.S1"));
1354 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"
1355 ".ExperimentGroup0"));
1356 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"
1357 ".ExperimentGroup0"));
1358 EXPECT_EQ(kInterFrameDelayMs1,
1359 metrics::MinSample("WebRTC.Video.InterframeDelayInMs.S0"));
1360 EXPECT_EQ(kInterFrameDelayMs2,
1361 metrics::MinSample("WebRTC.Video.InterframeDelayInMs.S1"));
1362 EXPECT_EQ((kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1363 metrics::MinSample("WebRTC.Video.InterframeDelayInMs"));
1364 EXPECT_EQ(kInterFrameDelayMs2,
1365 metrics::MinSample("WebRTC.Video.InterframeDelayMaxInMs"));
1366 EXPECT_EQ((kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1367 metrics::MinSample(
1368 "WebRTC.Video.InterframeDelayInMs.ExperimentGroup0"));
1369 }
1370}
sakale5ba44e2016-10-26 07:09:24 -07001371} // namespace webrtc