blob: 44fdc8bd151f0307142f21b92ecd8aa28a501992 [file] [log] [blame]
sakale5ba44e2016-10-26 07:09:24 -07001/*
2 * Copyright 2016 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "video/receive_statistics_proxy.h"
sakale5ba44e2016-10-26 07:09:24 -070012
asapersson2077f2f2017-05-11 05:37:35 -070013#include <limits>
sakale5ba44e2016-10-26 07:09:24 -070014#include <memory>
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +020015#include <utility>
sakale5ba44e2016-10-26 07:09:24 -070016
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "api/video/i420_buffer.h"
18#include "api/video/video_frame.h"
19#include "api/video/video_rotation.h"
20#include "modules/video_coding/include/video_codec_interface.h"
21#include "system_wrappers/include/metrics.h"
22#include "system_wrappers/include/metrics_default.h"
23#include "test/gtest.h"
sakale5ba44e2016-10-26 07:09:24 -070024
25namespace webrtc {
asaperssonde9e5ff2016-11-02 07:14:03 -070026namespace {
27const int64_t kFreqOffsetProcessIntervalInMs = 40000;
asapersson46c4e3c2016-11-03 06:48:19 -070028const uint32_t kLocalSsrc = 123;
29const uint32_t kRemoteSsrc = 456;
30const int kMinRequiredSamples = 200;
asaperssonde9e5ff2016-11-02 07:14:03 -070031} // namespace
sakale5ba44e2016-10-26 07:09:24 -070032
33// TODO(sakal): ReceiveStatisticsProxy is lacking unittesting.
sprang892dab52017-08-15 05:00:33 -070034class ReceiveStatisticsProxyTest
35 : public ::testing::TestWithParam<webrtc::VideoContentType> {
sakale5ba44e2016-10-26 07:09:24 -070036 public:
37 ReceiveStatisticsProxyTest() : fake_clock_(1234), config_(GetTestConfig()) {}
38 virtual ~ReceiveStatisticsProxyTest() {}
39
40 protected:
41 virtual void SetUp() {
asaperssonde9e5ff2016-11-02 07:14:03 -070042 metrics::Reset();
sakale5ba44e2016-10-26 07:09:24 -070043 statistics_proxy_.reset(new ReceiveStatisticsProxy(&config_, &fake_clock_));
44 }
45
46 VideoReceiveStream::Config GetTestConfig() {
47 VideoReceiveStream::Config config(nullptr);
asapersson46c4e3c2016-11-03 06:48:19 -070048 config.rtp.local_ssrc = kLocalSsrc;
49 config.rtp.remote_ssrc = kRemoteSsrc;
sakale5ba44e2016-10-26 07:09:24 -070050 return config;
51 }
52
asapersson2077f2f2017-05-11 05:37:35 -070053 void InsertFirstRtpPacket(uint32_t ssrc) {
54 StreamDataCounters counters;
55 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
56 statistics_proxy_->DataCountersUpdated(counters, ssrc);
57 }
58
59 VideoFrame CreateFrame(int width, int height) {
60 VideoFrame frame(I420Buffer::Create(width, height), 0, 0, kVideoRotation_0);
61 frame.set_ntp_time_ms(fake_clock_.CurrentNtpInMilliseconds());
62 return frame;
63 }
64
sakale5ba44e2016-10-26 07:09:24 -070065 SimulatedClock fake_clock_;
asaperssonde9e5ff2016-11-02 07:14:03 -070066 const VideoReceiveStream::Config config_;
sakale5ba44e2016-10-26 07:09:24 -070067 std::unique_ptr<ReceiveStatisticsProxy> statistics_proxy_;
sakale5ba44e2016-10-26 07:09:24 -070068};
69
70TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameIncreasesFramesDecoded) {
71 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_decoded);
72 for (uint32_t i = 1; i <= 3; ++i) {
ilnik00d802b2017-04-11 10:34:31 -070073 statistics_proxy_->OnDecodedFrame(rtc::Optional<uint8_t>(),
74 VideoContentType::UNSPECIFIED);
sakale5ba44e2016-10-26 07:09:24 -070075 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_decoded);
76 }
77}
78
sakalcc452e12017-02-09 04:53:45 -080079TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameWithQpResetsFramesDecoded) {
80 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_decoded);
81 for (uint32_t i = 1; i <= 3; ++i) {
ilnik00d802b2017-04-11 10:34:31 -070082 statistics_proxy_->OnDecodedFrame(rtc::Optional<uint8_t>(),
83 VideoContentType::UNSPECIFIED);
sakalcc452e12017-02-09 04:53:45 -080084 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_decoded);
85 }
ilnik00d802b2017-04-11 10:34:31 -070086 statistics_proxy_->OnDecodedFrame(rtc::Optional<uint8_t>(1u),
87 VideoContentType::UNSPECIFIED);
sakalcc452e12017-02-09 04:53:45 -080088 EXPECT_EQ(1u, statistics_proxy_->GetStats().frames_decoded);
89}
90
91TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameIncreasesQpSum) {
92 EXPECT_EQ(rtc::Optional<uint64_t>(), statistics_proxy_->GetStats().qp_sum);
ilnik00d802b2017-04-11 10:34:31 -070093 statistics_proxy_->OnDecodedFrame(rtc::Optional<uint8_t>(3u),
94 VideoContentType::UNSPECIFIED);
sakalcc452e12017-02-09 04:53:45 -080095 EXPECT_EQ(rtc::Optional<uint64_t>(3u), statistics_proxy_->GetStats().qp_sum);
ilnik00d802b2017-04-11 10:34:31 -070096 statistics_proxy_->OnDecodedFrame(rtc::Optional<uint8_t>(127u),
97 VideoContentType::UNSPECIFIED);
sakalcc452e12017-02-09 04:53:45 -080098 EXPECT_EQ(rtc::Optional<uint64_t>(130u),
99 statistics_proxy_->GetStats().qp_sum);
100}
101
ilnik2e1b40b2017-09-04 07:57:17 -0700102TEST_F(ReceiveStatisticsProxyTest, ReportsContentType) {
103 const std::string kRealtimeString("realtime");
104 const std::string kScreenshareString("screen");
105 EXPECT_EQ(kRealtimeString, videocontenttypehelpers::ToString(
106 statistics_proxy_->GetStats().content_type));
107 statistics_proxy_->OnDecodedFrame(rtc::Optional<uint8_t>(3u),
108 VideoContentType::SCREENSHARE);
109 EXPECT_EQ(kScreenshareString, videocontenttypehelpers::ToString(
110 statistics_proxy_->GetStats().content_type));
111 statistics_proxy_->OnDecodedFrame(rtc::Optional<uint8_t>(3u),
112 VideoContentType::UNSPECIFIED);
113 EXPECT_EQ(kRealtimeString, videocontenttypehelpers::ToString(
114 statistics_proxy_->GetStats().content_type));
115}
116
ilnika79cc282017-08-23 05:24:10 -0700117TEST_F(ReceiveStatisticsProxyTest, ReportsMaxInterframeDelay) {
118 const int64_t kInterframeDelayMs1 = 100;
119 const int64_t kInterframeDelayMs2 = 200;
120 const int64_t kInterframeDelayMs3 = 100;
121 EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
ilnikf04afde2017-07-07 01:26:24 -0700122 statistics_proxy_->OnDecodedFrame(rtc::Optional<uint8_t>(3u),
123 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700124 EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
ilnikf04afde2017-07-07 01:26:24 -0700125
126 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs1);
127 statistics_proxy_->OnDecodedFrame(rtc::Optional<uint8_t>(127u),
128 VideoContentType::UNSPECIFIED);
129 EXPECT_EQ(kInterframeDelayMs1,
ilnika79cc282017-08-23 05:24:10 -0700130 statistics_proxy_->GetStats().interframe_delay_max_ms);
ilnikf04afde2017-07-07 01:26:24 -0700131
132 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs2);
133 statistics_proxy_->OnDecodedFrame(rtc::Optional<uint8_t>(127u),
134 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700135 EXPECT_EQ(kInterframeDelayMs2,
136 statistics_proxy_->GetStats().interframe_delay_max_ms);
137
138 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs3);
139 statistics_proxy_->OnDecodedFrame(rtc::Optional<uint8_t>(127u),
140 VideoContentType::UNSPECIFIED);
141 // kInterframeDelayMs3 is smaller than kInterframeDelayMs2.
142 EXPECT_EQ(kInterframeDelayMs2,
143 statistics_proxy_->GetStats().interframe_delay_max_ms);
144}
145
146TEST_F(ReceiveStatisticsProxyTest, ReportInterframeDelayInWindow) {
Ilya Nikolaevskiyb06b3582017-10-16 17:59:12 +0200147 const int64_t kInterframeDelayMs1 = 900;
148 const int64_t kInterframeDelayMs2 = 750;
149 const int64_t kInterframeDelayMs3 = 700;
ilnika79cc282017-08-23 05:24:10 -0700150 EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
151 statistics_proxy_->OnDecodedFrame(rtc::Optional<uint8_t>(3u),
152 VideoContentType::UNSPECIFIED);
153 EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
154
155 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs1);
156 statistics_proxy_->OnDecodedFrame(rtc::Optional<uint8_t>(127u),
157 VideoContentType::UNSPECIFIED);
158 EXPECT_EQ(kInterframeDelayMs1,
159 statistics_proxy_->GetStats().interframe_delay_max_ms);
160
161 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs2);
162 statistics_proxy_->OnDecodedFrame(rtc::Optional<uint8_t>(127u),
163 VideoContentType::UNSPECIFIED);
164 // Still first delay is the maximum
165 EXPECT_EQ(kInterframeDelayMs1,
166 statistics_proxy_->GetStats().interframe_delay_max_ms);
167
168 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs3);
169 statistics_proxy_->OnDecodedFrame(rtc::Optional<uint8_t>(127u),
170 VideoContentType::UNSPECIFIED);
171 // Now the first sample is out of the window, so the second is the maximum.
172 EXPECT_EQ(kInterframeDelayMs2,
173 statistics_proxy_->GetStats().interframe_delay_max_ms);
ilnikf04afde2017-07-07 01:26:24 -0700174}
175
sakalcc452e12017-02-09 04:53:45 -0800176TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameWithoutQpQpSumWontExist) {
177 EXPECT_EQ(rtc::Optional<uint64_t>(), statistics_proxy_->GetStats().qp_sum);
ilnik00d802b2017-04-11 10:34:31 -0700178 statistics_proxy_->OnDecodedFrame(rtc::Optional<uint8_t>(),
179 VideoContentType::UNSPECIFIED);
sakalcc452e12017-02-09 04:53:45 -0800180 EXPECT_EQ(rtc::Optional<uint64_t>(), statistics_proxy_->GetStats().qp_sum);
181}
182
183TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameWithoutQpResetsQpSum) {
184 EXPECT_EQ(rtc::Optional<uint64_t>(), statistics_proxy_->GetStats().qp_sum);
ilnik00d802b2017-04-11 10:34:31 -0700185 statistics_proxy_->OnDecodedFrame(rtc::Optional<uint8_t>(3u),
186 VideoContentType::UNSPECIFIED);
sakalcc452e12017-02-09 04:53:45 -0800187 EXPECT_EQ(rtc::Optional<uint64_t>(3u), statistics_proxy_->GetStats().qp_sum);
ilnik00d802b2017-04-11 10:34:31 -0700188 statistics_proxy_->OnDecodedFrame(rtc::Optional<uint8_t>(),
189 VideoContentType::UNSPECIFIED);
sakalcc452e12017-02-09 04:53:45 -0800190 EXPECT_EQ(rtc::Optional<uint64_t>(), statistics_proxy_->GetStats().qp_sum);
191}
192
hbos50cfe1f2017-01-23 07:21:55 -0800193TEST_F(ReceiveStatisticsProxyTest, OnRenderedFrameIncreasesFramesRendered) {
194 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_rendered);
ilnik00d802b2017-04-11 10:34:31 -0700195 webrtc::VideoFrame frame(webrtc::I420Buffer::Create(1, 1), 0, 0,
196 webrtc::kVideoRotation_0);
hbos50cfe1f2017-01-23 07:21:55 -0800197 for (uint32_t i = 1; i <= 3; ++i) {
198 statistics_proxy_->OnRenderedFrame(frame);
199 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_rendered);
200 }
201}
202
asapersson46c4e3c2016-11-03 06:48:19 -0700203TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsSsrc) {
204 EXPECT_EQ(kRemoteSsrc, statistics_proxy_->GetStats().ssrc);
205}
206
207TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsIncomingPayloadType) {
208 const int kPayloadType = 111;
209 statistics_proxy_->OnIncomingPayloadType(kPayloadType);
210 EXPECT_EQ(kPayloadType, statistics_proxy_->GetStats().current_payload_type);
211}
212
asapersson6966bd52017-01-03 00:44:06 -0800213TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsDecoderImplementationName) {
214 const char* kName = "decoderName";
215 statistics_proxy_->OnDecoderImplementationName(kName);
216 EXPECT_STREQ(
217 kName, statistics_proxy_->GetStats().decoder_implementation_name.c_str());
218}
219
philipela45102f2017-02-22 05:30:39 -0800220TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsOnCompleteFrame) {
221 const int kFrameSizeBytes = 1000;
ilnik6d5b4d62017-08-30 03:32:14 -0700222 statistics_proxy_->OnCompleteFrame(true, kFrameSizeBytes,
223 VideoContentType::UNSPECIFIED);
philipela45102f2017-02-22 05:30:39 -0800224 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
225 EXPECT_EQ(1, stats.network_frame_rate);
philipela45102f2017-02-22 05:30:39 -0800226 EXPECT_EQ(1, stats.frame_counts.key_frames);
227 EXPECT_EQ(0, stats.frame_counts.delta_frames);
asapersson46c4e3c2016-11-03 06:48:19 -0700228}
229
230TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsDecodeTimingStats) {
231 const int kDecodeMs = 1;
232 const int kMaxDecodeMs = 2;
233 const int kCurrentDelayMs = 3;
234 const int kTargetDelayMs = 4;
235 const int kJitterBufferMs = 5;
236 const int kMinPlayoutDelayMs = 6;
237 const int kRenderDelayMs = 7;
238 const int64_t kRttMs = 8;
philipela45102f2017-02-22 05:30:39 -0800239 statistics_proxy_->OnRttUpdate(kRttMs, 0);
240 statistics_proxy_->OnFrameBufferTimingsUpdated(
asapersson46c4e3c2016-11-03 06:48:19 -0700241 kDecodeMs, kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs, kJitterBufferMs,
philipela45102f2017-02-22 05:30:39 -0800242 kMinPlayoutDelayMs, kRenderDelayMs);
asapersson46c4e3c2016-11-03 06:48:19 -0700243 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
244 EXPECT_EQ(kDecodeMs, stats.decode_ms);
245 EXPECT_EQ(kMaxDecodeMs, stats.max_decode_ms);
246 EXPECT_EQ(kCurrentDelayMs, stats.current_delay_ms);
247 EXPECT_EQ(kTargetDelayMs, stats.target_delay_ms);
248 EXPECT_EQ(kJitterBufferMs, stats.jitter_buffer_ms);
249 EXPECT_EQ(kMinPlayoutDelayMs, stats.min_playout_delay_ms);
250 EXPECT_EQ(kRenderDelayMs, stats.render_delay_ms);
251}
252
asapersson6966bd52017-01-03 00:44:06 -0800253TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsRtcpPacketTypeCounts) {
254 const uint32_t kFirPackets = 33;
255 const uint32_t kPliPackets = 44;
256 const uint32_t kNackPackets = 55;
257 RtcpPacketTypeCounter counter;
258 counter.fir_packets = kFirPackets;
259 counter.pli_packets = kPliPackets;
260 counter.nack_packets = kNackPackets;
261 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc, counter);
262 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
263 EXPECT_EQ(kFirPackets, stats.rtcp_packet_type_counts.fir_packets);
264 EXPECT_EQ(kPliPackets, stats.rtcp_packet_type_counts.pli_packets);
265 EXPECT_EQ(kNackPackets, stats.rtcp_packet_type_counts.nack_packets);
266}
267
268TEST_F(ReceiveStatisticsProxyTest,
269 GetStatsReportsNoRtcpPacketTypeCountsForUnknownSsrc) {
270 RtcpPacketTypeCounter counter;
271 counter.fir_packets = 33;
272 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc + 1, counter);
273 EXPECT_EQ(0u,
274 statistics_proxy_->GetStats().rtcp_packet_type_counts.fir_packets);
275}
276
277TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsFrameCounts) {
278 const int kKeyFrames = 3;
279 const int kDeltaFrames = 22;
280 FrameCounts frame_counts;
281 frame_counts.key_frames = kKeyFrames;
282 frame_counts.delta_frames = kDeltaFrames;
283 statistics_proxy_->OnFrameCountsUpdated(frame_counts);
284 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
285 EXPECT_EQ(kKeyFrames, stats.frame_counts.key_frames);
286 EXPECT_EQ(kDeltaFrames, stats.frame_counts.delta_frames);
287}
288
asapersson46c4e3c2016-11-03 06:48:19 -0700289TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsDiscardedPackets) {
290 const int kDiscardedPackets = 12;
291 statistics_proxy_->OnDiscardedPacketsUpdated(kDiscardedPackets);
292 EXPECT_EQ(kDiscardedPackets, statistics_proxy_->GetStats().discarded_packets);
293}
294
asapersson6966bd52017-01-03 00:44:06 -0800295TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsRtcpStats) {
296 const uint8_t kFracLost = 0;
297 const uint32_t kCumLost = 1;
298 const uint32_t kExtSeqNum = 10;
299 const uint32_t kJitter = 4;
300
301 RtcpStatistics rtcp_stats;
302 rtcp_stats.fraction_lost = kFracLost;
srte186d9c32017-08-04 05:03:53 -0700303 rtcp_stats.packets_lost = kCumLost;
304 rtcp_stats.extended_highest_sequence_number = kExtSeqNum;
asapersson6966bd52017-01-03 00:44:06 -0800305 rtcp_stats.jitter = kJitter;
306 statistics_proxy_->StatisticsUpdated(rtcp_stats, kRemoteSsrc);
307
308 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
309 EXPECT_EQ(kFracLost, stats.rtcp_stats.fraction_lost);
srte186d9c32017-08-04 05:03:53 -0700310 EXPECT_EQ(kCumLost, stats.rtcp_stats.packets_lost);
311 EXPECT_EQ(kExtSeqNum, stats.rtcp_stats.extended_highest_sequence_number);
asapersson6966bd52017-01-03 00:44:06 -0800312 EXPECT_EQ(kJitter, stats.rtcp_stats.jitter);
313}
314
315TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsCName) {
316 const char* kName = "cName";
317 statistics_proxy_->CNameChanged(kName, kRemoteSsrc);
318 EXPECT_STREQ(kName, statistics_proxy_->GetStats().c_name.c_str());
319}
320
321TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsNoCNameForUnknownSsrc) {
322 const char* kName = "cName";
323 statistics_proxy_->CNameChanged(kName, kRemoteSsrc + 1);
324 EXPECT_STREQ("", statistics_proxy_->GetStats().c_name.c_str());
325}
326
ilnik2edc6842017-07-06 03:06:50 -0700327TEST_F(ReceiveStatisticsProxyTest,
ilnik75204c52017-09-04 03:35:40 -0700328 ReportsLongestTimingFrameInfo) {
ilnik2edc6842017-07-06 03:06:50 -0700329 const int64_t kShortEndToEndDelay = 10;
330 const int64_t kMedEndToEndDelay = 20;
331 const int64_t kLongEndToEndDelay = 100;
332 const uint32_t kExpectedRtpTimestamp = 2;
333 TimingFrameInfo info;
334 rtc::Optional<TimingFrameInfo> result;
335 info.rtp_timestamp = kExpectedRtpTimestamp - 1;
336 info.capture_time_ms = 0;
337 info.decode_finish_ms = kShortEndToEndDelay;
338 statistics_proxy_->OnTimingFrameInfoUpdated(info);
339 info.rtp_timestamp =
340 kExpectedRtpTimestamp; // this frame should be reported in the end.
341 info.capture_time_ms = 0;
342 info.decode_finish_ms = kLongEndToEndDelay;
343 statistics_proxy_->OnTimingFrameInfoUpdated(info);
344 info.rtp_timestamp = kExpectedRtpTimestamp + 1;
345 info.capture_time_ms = 0;
346 info.decode_finish_ms = kMedEndToEndDelay;
347 statistics_proxy_->OnTimingFrameInfoUpdated(info);
ilnik75204c52017-09-04 03:35:40 -0700348 result = statistics_proxy_->GetStats().timing_frame_info;
ilnik2edc6842017-07-06 03:06:50 -0700349 EXPECT_TRUE(result);
350 EXPECT_EQ(kExpectedRtpTimestamp, result->rtp_timestamp);
351}
352
ilnik75204c52017-09-04 03:35:40 -0700353TEST_F(ReceiveStatisticsProxyTest, RespectsReportingIntervalForTimingFrames) {
354 TimingFrameInfo info;
ilnik2edc6842017-07-06 03:06:50 -0700355 const int64_t kShortEndToEndDelay = 10;
356 const uint32_t kExpectedRtpTimestamp = 2;
ilnik75204c52017-09-04 03:35:40 -0700357 const int64_t kShortDelayMs = 1000;
358 const int64_t kLongDelayMs = 10000;
ilnik2edc6842017-07-06 03:06:50 -0700359 rtc::Optional<TimingFrameInfo> result;
360 info.rtp_timestamp = kExpectedRtpTimestamp;
361 info.capture_time_ms = 0;
362 info.decode_finish_ms = kShortEndToEndDelay;
363 statistics_proxy_->OnTimingFrameInfoUpdated(info);
ilnik75204c52017-09-04 03:35:40 -0700364 fake_clock_.AdvanceTimeMilliseconds(kShortDelayMs);
365 result = statistics_proxy_->GetStats().timing_frame_info;
ilnik2edc6842017-07-06 03:06:50 -0700366 EXPECT_TRUE(result);
367 EXPECT_EQ(kExpectedRtpTimestamp, result->rtp_timestamp);
ilnik75204c52017-09-04 03:35:40 -0700368 fake_clock_.AdvanceTimeMilliseconds(kLongDelayMs);
369 result = statistics_proxy_->GetStats().timing_frame_info;
ilnik2edc6842017-07-06 03:06:50 -0700370 EXPECT_FALSE(result);
371}
372
asapersson46c4e3c2016-11-03 06:48:19 -0700373TEST_F(ReceiveStatisticsProxyTest, LifetimeHistogramIsUpdated) {
374 const int64_t kTimeSec = 3;
375 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
ilnik6d5b4d62017-08-30 03:32:14 -0700376 // Need at least one frame to report stream lifetime.
377 statistics_proxy_->OnCompleteFrame(true, 1000, VideoContentType::UNSPECIFIED);
asapersson46c4e3c2016-11-03 06:48:19 -0700378 // Histograms are updated when the statistics_proxy_ is deleted.
379 statistics_proxy_.reset();
380 EXPECT_EQ(1,
381 metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
382 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.ReceiveStreamLifetimeInSeconds",
383 kTimeSec));
384}
385
ilnik6d5b4d62017-08-30 03:32:14 -0700386TEST_F(ReceiveStatisticsProxyTest,
387 LifetimeHistogramNotReportedForEmptyStreams) {
388 const int64_t kTimeSec = 3;
389 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
390 // No frames received.
391 // Histograms are updated when the statistics_proxy_ is deleted.
392 statistics_proxy_.reset();
393 EXPECT_EQ(0,
394 metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
395}
396
palmkvista40672a2017-01-13 05:58:34 -0800397TEST_F(ReceiveStatisticsProxyTest, BadCallHistogramsAreUpdated) {
398 // Based on the tuning parameters this will produce 7 uncertain states,
399 // then 10 certainly bad states. There has to be 10 certain states before
400 // any histograms are recorded.
401 const int kNumBadSamples = 17;
402
403 StreamDataCounters counters;
404 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
405 statistics_proxy_->DataCountersUpdated(counters, config_.rtp.remote_ssrc);
406
407 for (int i = 0; i < kNumBadSamples; ++i) {
408 // Since OnRenderedFrame is never called the fps in each sample will be 0,
409 // i.e. bad
410 fake_clock_.AdvanceTimeMilliseconds(1000);
411 statistics_proxy_->OnIncomingRate(0, 0);
412 }
413 // Histograms are updated when the statistics_proxy_ is deleted.
414 statistics_proxy_.reset();
415 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BadCall.Any"));
416 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BadCall.Any", 100));
417
418 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BadCall.FrameRate"));
419 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BadCall.FrameRate", 100));
420
421 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.BadCall.FrameRateVariance"));
422
423 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.BadCall.Qp"));
424}
425
asapersson0c43f772016-11-30 01:42:26 -0800426TEST_F(ReceiveStatisticsProxyTest, PacketLossHistogramIsUpdated) {
427 const uint32_t kCumLost1 = 1;
428 const uint32_t kExtSeqNum1 = 10;
429 const uint32_t kCumLost2 = 2;
430 const uint32_t kExtSeqNum2 = 20;
431
432 // One report block received.
433 RtcpStatistics rtcp_stats1;
srte186d9c32017-08-04 05:03:53 -0700434 rtcp_stats1.packets_lost = kCumLost1;
435 rtcp_stats1.extended_highest_sequence_number = kExtSeqNum1;
asapersson0c43f772016-11-30 01:42:26 -0800436 statistics_proxy_->StatisticsUpdated(rtcp_stats1, kRemoteSsrc);
437
438 // Two report blocks received.
439 RtcpStatistics rtcp_stats2;
srte186d9c32017-08-04 05:03:53 -0700440 rtcp_stats2.packets_lost = kCumLost2;
441 rtcp_stats2.extended_highest_sequence_number = kExtSeqNum2;
asapersson0c43f772016-11-30 01:42:26 -0800442 statistics_proxy_->StatisticsUpdated(rtcp_stats2, kRemoteSsrc);
443
444 // Two received report blocks but min run time has not passed.
445 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
446 SetUp(); // Reset stat proxy causes histograms to be updated.
447 EXPECT_EQ(0,
448 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
449
450 // Two report blocks received.
451 statistics_proxy_->StatisticsUpdated(rtcp_stats1, kRemoteSsrc);
452 statistics_proxy_->StatisticsUpdated(rtcp_stats2, kRemoteSsrc);
453
454 // Two received report blocks and min run time has passed.
455 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
456 SetUp();
457 EXPECT_EQ(1,
458 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
459 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.ReceivedPacketsLostInPercent",
460 (kCumLost2 - kCumLost1) * 100 /
461 (kExtSeqNum2 - kExtSeqNum1)));
462}
463
464TEST_F(ReceiveStatisticsProxyTest,
465 PacketLossHistogramIsNotUpdatedIfLessThanTwoReportBlocksAreReceived) {
466 RtcpStatistics rtcp_stats1;
srte186d9c32017-08-04 05:03:53 -0700467 rtcp_stats1.packets_lost = 1;
468 rtcp_stats1.extended_highest_sequence_number = 10;
asapersson0c43f772016-11-30 01:42:26 -0800469
470 // Min run time has passed but no received report block.
471 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
472 SetUp(); // Reset stat proxy causes histograms to be updated.
473 EXPECT_EQ(0,
474 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
475
476 // Min run time has passed but only one received report block.
477 statistics_proxy_->StatisticsUpdated(rtcp_stats1, kRemoteSsrc);
478 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
479 SetUp();
480 EXPECT_EQ(0,
481 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
482}
483
asapersson2077f2f2017-05-11 05:37:35 -0700484TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsAvSyncOffset) {
485 const int64_t kSyncOffsetMs = 22;
486 const double kFreqKhz = 90.0;
487 EXPECT_EQ(std::numeric_limits<int>::max(),
488 statistics_proxy_->GetStats().sync_offset_ms);
489 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
490 EXPECT_EQ(kSyncOffsetMs, statistics_proxy_->GetStats().sync_offset_ms);
491}
492
asapersson46c4e3c2016-11-03 06:48:19 -0700493TEST_F(ReceiveStatisticsProxyTest, AvSyncOffsetHistogramIsUpdated) {
494 const int64_t kSyncOffsetMs = 22;
495 const double kFreqKhz = 90.0;
496 for (int i = 0; i < kMinRequiredSamples; ++i)
497 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
498 // Histograms are updated when the statistics_proxy_ is deleted.
499 statistics_proxy_.reset();
500 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AVSyncOffsetInMs"));
501 EXPECT_EQ(1,
502 metrics::NumEvents("WebRTC.Video.AVSyncOffsetInMs", kSyncOffsetMs));
503}
504
asaperssonde9e5ff2016-11-02 07:14:03 -0700505TEST_F(ReceiveStatisticsProxyTest, RtpToNtpFrequencyOffsetHistogramIsUpdated) {
506 const int64_t kSyncOffsetMs = 22;
507 const double kFreqKhz = 90.0;
508 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
509 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz + 2.2);
510 fake_clock_.AdvanceTimeMilliseconds(kFreqOffsetProcessIntervalInMs);
511 // Process interval passed, max diff: 2.
512 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz + 1.1);
513 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz - 4.2);
514 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz - 0.9);
515 fake_clock_.AdvanceTimeMilliseconds(kFreqOffsetProcessIntervalInMs);
516 // Process interval passed, max diff: 4.
517 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
518 statistics_proxy_.reset();
519 // Average reported: (2 + 4) / 2 = 3.
520 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtpToNtpFreqOffsetInKhz"));
521 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtpToNtpFreqOffsetInKhz", 3));
522}
523
asapersson6966bd52017-01-03 00:44:06 -0800524TEST_F(ReceiveStatisticsProxyTest, Vp8QpHistogramIsUpdated) {
525 const int kQp = 22;
526 EncodedImage encoded_image;
527 encoded_image.qp_ = kQp;
528 CodecSpecificInfo codec_info;
529 codec_info.codecType = kVideoCodecVP8;
530
531 for (int i = 0; i < kMinRequiredSamples; ++i)
532 statistics_proxy_->OnPreDecode(encoded_image, &codec_info);
533
534 statistics_proxy_.reset();
535 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
536 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Decoded.Vp8.Qp", kQp));
537}
538
539TEST_F(ReceiveStatisticsProxyTest, Vp8QpHistogramIsNotUpdatedForTooFewSamples) {
540 EncodedImage encoded_image;
541 encoded_image.qp_ = 22;
542 CodecSpecificInfo codec_info;
543 codec_info.codecType = kVideoCodecVP8;
544
545 for (int i = 0; i < kMinRequiredSamples - 1; ++i)
546 statistics_proxy_->OnPreDecode(encoded_image, &codec_info);
547
548 statistics_proxy_.reset();
549 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
550}
551
552TEST_F(ReceiveStatisticsProxyTest, Vp8QpHistogramIsNotUpdatedIfNoQpValue) {
553 EncodedImage encoded_image;
554 CodecSpecificInfo codec_info;
555 codec_info.codecType = kVideoCodecVP8;
556
557 for (int i = 0; i < kMinRequiredSamples; ++i)
558 statistics_proxy_->OnPreDecode(encoded_image, &codec_info);
559
560 statistics_proxy_.reset();
561 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
562}
563
asaperssonb99baf82017-04-20 04:05:43 -0700564TEST_F(ReceiveStatisticsProxyTest,
565 KeyFrameHistogramNotUpdatedForTooFewSamples) {
566 const bool kIsKeyFrame = false;
567 const int kFrameSizeBytes = 1000;
568
569 for (int i = 0; i < kMinRequiredSamples - 1; ++i)
ilnik6d5b4d62017-08-30 03:32:14 -0700570 statistics_proxy_->OnCompleteFrame(kIsKeyFrame, kFrameSizeBytes,
571 VideoContentType::UNSPECIFIED);
asaperssonb99baf82017-04-20 04:05:43 -0700572
573 EXPECT_EQ(0, statistics_proxy_->GetStats().frame_counts.key_frames);
574 EXPECT_EQ(kMinRequiredSamples - 1,
575 statistics_proxy_->GetStats().frame_counts.delta_frames);
576
577 statistics_proxy_.reset();
578 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
579}
580
581TEST_F(ReceiveStatisticsProxyTest,
582 KeyFrameHistogramUpdatedForMinRequiredSamples) {
583 const bool kIsKeyFrame = false;
584 const int kFrameSizeBytes = 1000;
585
586 for (int i = 0; i < kMinRequiredSamples; ++i)
ilnik6d5b4d62017-08-30 03:32:14 -0700587 statistics_proxy_->OnCompleteFrame(kIsKeyFrame, kFrameSizeBytes,
588 VideoContentType::UNSPECIFIED);
asaperssonb99baf82017-04-20 04:05:43 -0700589
590 EXPECT_EQ(0, statistics_proxy_->GetStats().frame_counts.key_frames);
591 EXPECT_EQ(kMinRequiredSamples,
592 statistics_proxy_->GetStats().frame_counts.delta_frames);
593
594 statistics_proxy_.reset();
595 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
596 EXPECT_EQ(1,
597 metrics::NumEvents("WebRTC.Video.KeyFramesReceivedInPermille", 0));
598}
599
600TEST_F(ReceiveStatisticsProxyTest, KeyFrameHistogramIsUpdated) {
601 const int kFrameSizeBytes = 1000;
602
603 for (int i = 0; i < kMinRequiredSamples; ++i)
ilnik6d5b4d62017-08-30 03:32:14 -0700604 statistics_proxy_->OnCompleteFrame(true, kFrameSizeBytes,
605 VideoContentType::UNSPECIFIED);
asaperssonb99baf82017-04-20 04:05:43 -0700606
607 for (int i = 0; i < kMinRequiredSamples; ++i)
ilnik6d5b4d62017-08-30 03:32:14 -0700608 statistics_proxy_->OnCompleteFrame(false, kFrameSizeBytes,
609 VideoContentType::UNSPECIFIED);
asaperssonb99baf82017-04-20 04:05:43 -0700610
611 EXPECT_EQ(kMinRequiredSamples,
612 statistics_proxy_->GetStats().frame_counts.key_frames);
613 EXPECT_EQ(kMinRequiredSamples,
614 statistics_proxy_->GetStats().frame_counts.delta_frames);
615
616 statistics_proxy_.reset();
617 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
618 EXPECT_EQ(
619 1, metrics::NumEvents("WebRTC.Video.KeyFramesReceivedInPermille", 500));
620}
621
622TEST_F(ReceiveStatisticsProxyTest, TimingHistogramsNotUpdatedForTooFewSamples) {
623 const int kDecodeMs = 1;
624 const int kMaxDecodeMs = 2;
625 const int kCurrentDelayMs = 3;
626 const int kTargetDelayMs = 4;
627 const int kJitterBufferMs = 5;
628 const int kMinPlayoutDelayMs = 6;
629 const int kRenderDelayMs = 7;
630
631 for (int i = 0; i < kMinRequiredSamples - 1; ++i) {
632 statistics_proxy_->OnFrameBufferTimingsUpdated(
633 kDecodeMs, kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs,
634 kJitterBufferMs, kMinPlayoutDelayMs, kRenderDelayMs);
635 }
636
637 statistics_proxy_.reset();
638 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
639 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
640 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
641 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
642 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
643}
644
645TEST_F(ReceiveStatisticsProxyTest, TimingHistogramsAreUpdated) {
646 const int kDecodeMs = 1;
647 const int kMaxDecodeMs = 2;
648 const int kCurrentDelayMs = 3;
649 const int kTargetDelayMs = 4;
650 const int kJitterBufferMs = 5;
651 const int kMinPlayoutDelayMs = 6;
652 const int kRenderDelayMs = 7;
653
654 for (int i = 0; i < kMinRequiredSamples; ++i) {
655 statistics_proxy_->OnFrameBufferTimingsUpdated(
656 kDecodeMs, kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs,
657 kJitterBufferMs, kMinPlayoutDelayMs, kRenderDelayMs);
658 }
659
660 statistics_proxy_.reset();
661 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
662 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
663 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
664 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
665 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
666
667 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DecodeTimeInMs", kDecodeMs));
668 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.JitterBufferDelayInMs",
669 kJitterBufferMs));
670 EXPECT_EQ(1,
671 metrics::NumEvents("WebRTC.Video.TargetDelayInMs", kTargetDelayMs));
672 EXPECT_EQ(
673 1, metrics::NumEvents("WebRTC.Video.CurrentDelayInMs", kCurrentDelayMs));
674 EXPECT_EQ(1,
675 metrics::NumEvents("WebRTC.Video.OnewayDelayInMs", kTargetDelayMs));
676}
677
sprang948b2752017-05-04 02:47:13 -0700678TEST_F(ReceiveStatisticsProxyTest, DoesNotReportStaleFramerates) {
679 const int kDefaultFps = 30;
680 const int kWidth = 320;
681 const int kHeight = 240;
682
683 rtc::scoped_refptr<VideoFrameBuffer> video_frame_buffer(
684 I420Buffer::Create(kWidth, kHeight));
685 VideoFrame frame(video_frame_buffer, kVideoRotation_0, 0);
686
687 for (int i = 0; i < kDefaultFps; ++i) {
688 // Since OnRenderedFrame is never called the fps in each sample will be 0,
689 // i.e. bad
690 frame.set_ntp_time_ms(fake_clock_.CurrentNtpInMilliseconds());
691 statistics_proxy_->OnDecodedFrame(rtc::Optional<uint8_t>(),
692 VideoContentType::UNSPECIFIED);
693 statistics_proxy_->OnRenderedFrame(frame);
694 fake_clock_.AdvanceTimeMilliseconds(1000 / kDefaultFps);
695 }
696
697 EXPECT_EQ(kDefaultFps, statistics_proxy_->GetStats().decode_frame_rate);
698 EXPECT_EQ(kDefaultFps, statistics_proxy_->GetStats().render_frame_rate);
699
700 // FPS trackers in stats proxy have a 1000ms sliding window.
701 fake_clock_.AdvanceTimeMilliseconds(1000);
702 EXPECT_EQ(0, statistics_proxy_->GetStats().decode_frame_rate);
703 EXPECT_EQ(0, statistics_proxy_->GetStats().render_frame_rate);
704}
705
asapersson2077f2f2017-05-11 05:37:35 -0700706TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsReceivedFrameStats) {
707 const int kWidth = 160;
708 const int kHeight = 120;
709 EXPECT_EQ(0, statistics_proxy_->GetStats().width);
710 EXPECT_EQ(0, statistics_proxy_->GetStats().height);
711 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_rendered);
712
713 statistics_proxy_->OnRenderedFrame(CreateFrame(kWidth, kHeight));
714
715 EXPECT_EQ(kWidth, statistics_proxy_->GetStats().width);
716 EXPECT_EQ(kHeight, statistics_proxy_->GetStats().height);
717 EXPECT_EQ(1u, statistics_proxy_->GetStats().frames_rendered);
718}
719
720TEST_F(ReceiveStatisticsProxyTest,
721 ReceivedFrameHistogramsAreNotUpdatedForTooFewSamples) {
722 const int kWidth = 160;
723 const int kHeight = 120;
724
725 for (int i = 0; i < kMinRequiredSamples - 1; ++i)
726 statistics_proxy_->OnRenderedFrame(CreateFrame(kWidth, kHeight));
727
728 statistics_proxy_.reset();
729 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
730 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
731 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
732 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
733}
734
735TEST_F(ReceiveStatisticsProxyTest, ReceivedFrameHistogramsAreUpdated) {
736 const int kWidth = 160;
737 const int kHeight = 120;
738
739 for (int i = 0; i < kMinRequiredSamples; ++i)
740 statistics_proxy_->OnRenderedFrame(CreateFrame(kWidth, kHeight));
741
742 statistics_proxy_.reset();
743 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
744 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
745 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
746 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
747 EXPECT_EQ(1,
748 metrics::NumEvents("WebRTC.Video.ReceivedWidthInPixels", kWidth));
749 EXPECT_EQ(1,
750 metrics::NumEvents("WebRTC.Video.ReceivedHeightInPixels", kHeight));
751}
752
753TEST_F(ReceiveStatisticsProxyTest,
754 RtcpHistogramsNotUpdatedIfMinRuntimeHasNotPassed) {
755 InsertFirstRtpPacket(kRemoteSsrc);
756 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000) -
757 1);
758
759 RtcpPacketTypeCounter counter;
760 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc, counter);
761
762 statistics_proxy_.reset();
763 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
764 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
765 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
766}
767
768TEST_F(ReceiveStatisticsProxyTest, RtcpHistogramsAreUpdated) {
769 InsertFirstRtpPacket(kRemoteSsrc);
770 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
771
772 const uint32_t kFirPackets = 100;
773 const uint32_t kPliPackets = 200;
774 const uint32_t kNackPackets = 300;
775
776 RtcpPacketTypeCounter counter;
777 counter.fir_packets = kFirPackets;
778 counter.pli_packets = kPliPackets;
779 counter.nack_packets = kNackPackets;
780 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc, counter);
781
782 statistics_proxy_.reset();
783 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
784 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
785 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
786 EXPECT_EQ(
787 1, metrics::NumEvents("WebRTC.Video.FirPacketsSentPerMinute",
788 kFirPackets * 60 / metrics::kMinRunTimeInSeconds));
789 EXPECT_EQ(
790 1, metrics::NumEvents("WebRTC.Video.PliPacketsSentPerMinute",
791 kPliPackets * 60 / metrics::kMinRunTimeInSeconds));
792 EXPECT_EQ(
793 1, metrics::NumEvents("WebRTC.Video.NackPacketsSentPerMinute",
794 kNackPackets * 60 / metrics::kMinRunTimeInSeconds));
795}
796
sprang892dab52017-08-15 05:00:33 -0700797INSTANTIATE_TEST_CASE_P(ContentTypes,
798 ReceiveStatisticsProxyTest,
799 ::testing::Values(VideoContentType::UNSPECIFIED,
800 VideoContentType::SCREENSHARE));
801
802TEST_P(ReceiveStatisticsProxyTest, InterFrameDelaysAreReported) {
803 const VideoContentType content_type = GetParam();
804 const int kInterFrameDelayMs = 33;
805 for (int i = 0; i < kMinRequiredSamples; ++i) {
806 statistics_proxy_->OnDecodedFrame(rtc::Optional<uint8_t>(), content_type);
807 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
808 }
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +0200809 // One extra with double the interval.
sprang892dab52017-08-15 05:00:33 -0700810 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
811 statistics_proxy_->OnDecodedFrame(rtc::Optional<uint8_t>(), content_type);
812
813 statistics_proxy_.reset();
814 const int kExpectedInterFrame =
815 (kInterFrameDelayMs * (kMinRequiredSamples - 1) +
816 kInterFrameDelayMs * 2) /
817 kMinRequiredSamples;
ilnik6d5b4d62017-08-30 03:32:14 -0700818 if (videocontenttypehelpers::IsScreenshare(content_type)) {
819 EXPECT_EQ(
820 kExpectedInterFrame,
821 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs"));
822 EXPECT_EQ(
823 kInterFrameDelayMs * 2,
824 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
825 } else {
826 EXPECT_EQ(kExpectedInterFrame,
827 metrics::MinSample("WebRTC.Video.InterframeDelayInMs"));
828 EXPECT_EQ(kInterFrameDelayMs * 2,
829 metrics::MinSample("WebRTC.Video.InterframeDelayMaxInMs"));
sprang892dab52017-08-15 05:00:33 -0700830 }
831}
832
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +0200833TEST_P(ReceiveStatisticsProxyTest, InterFrameDelaysPercentilesAreReported) {
834 const VideoContentType content_type = GetParam();
835 const int kInterFrameDelayMs = 33;
836 const int kLastFivePercentsSamples = kMinRequiredSamples * 5 / 100;
837 for (int i = 0; i <= kMinRequiredSamples - kLastFivePercentsSamples; ++i) {
838 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
839 statistics_proxy_->OnDecodedFrame(rtc::Optional<uint8_t>(), content_type);
840 }
841 // Last 5% of intervals are double in size.
842 for (int i = 0; i < kLastFivePercentsSamples; ++i) {
843 fake_clock_.AdvanceTimeMilliseconds(2 * kInterFrameDelayMs);
844 statistics_proxy_->OnDecodedFrame(rtc::Optional<uint8_t>(), content_type);
845 }
846 // Final sample is outlier and 10 times as big.
847 fake_clock_.AdvanceTimeMilliseconds(10 * kInterFrameDelayMs);
848 statistics_proxy_->OnDecodedFrame(rtc::Optional<uint8_t>(), content_type);
849
850 statistics_proxy_.reset();
851 const int kExpectedInterFrame = kInterFrameDelayMs * 2;
852 if (videocontenttypehelpers::IsScreenshare(content_type)) {
853 EXPECT_EQ(kExpectedInterFrame,
854 metrics::MinSample(
855 "WebRTC.Video.Screenshare.InterframeDelay95PercentileInMs"));
856 } else {
857 EXPECT_EQ(
858 kExpectedInterFrame,
859 metrics::MinSample("WebRTC.Video.InterframeDelay95PercentileInMs"));
860 }
861}
862
sprang892dab52017-08-15 05:00:33 -0700863TEST_P(ReceiveStatisticsProxyTest, MaxInterFrameDelayOnlyWithValidAverage) {
864 const VideoContentType content_type = GetParam();
865 const int kInterFrameDelayMs = 33;
866 for (int i = 0; i < kMinRequiredSamples; ++i) {
867 statistics_proxy_->OnDecodedFrame(rtc::Optional<uint8_t>(), content_type);
868 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
869 }
870
871 // |kMinRequiredSamples| samples, and thereby intervals, is required. That
872 // means we're one frame short of having a valid data set.
873 statistics_proxy_.reset();
874 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
875 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
876 EXPECT_EQ(
877 0, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"));
878 EXPECT_EQ(0, metrics::NumSamples(
879 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
880}
881
sprang3e86e7e2017-08-22 09:23:28 -0700882TEST_P(ReceiveStatisticsProxyTest, MaxInterFrameDelayOnlyWithPause) {
883 const VideoContentType content_type = GetParam();
884 const int kInterFrameDelayMs = 33;
885 for (int i = 0; i <= kMinRequiredSamples; ++i) {
886 statistics_proxy_->OnDecodedFrame(rtc::Optional<uint8_t>(), content_type);
887 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
888 }
889
890 // At this state, we should have a valid inter-frame delay.
891 // Indicate stream paused and make a large jump in time.
892 statistics_proxy_->OnStreamInactive();
893 fake_clock_.AdvanceTimeMilliseconds(5000);
894
895 // Insert two more frames. The interval during the pause should be disregarded
896 // in the stats.
897 statistics_proxy_->OnDecodedFrame(rtc::Optional<uint8_t>(), content_type);
898 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
899 statistics_proxy_->OnDecodedFrame(rtc::Optional<uint8_t>(), content_type);
900
901 statistics_proxy_.reset();
ilnik6d5b4d62017-08-30 03:32:14 -0700902 if (videocontenttypehelpers::IsScreenshare(content_type)) {
sprang3e86e7e2017-08-22 09:23:28 -0700903 EXPECT_EQ(
904 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"));
905 EXPECT_EQ(1, metrics::NumSamples(
906 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
907 EXPECT_EQ(
908 kInterFrameDelayMs,
909 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs"));
910 EXPECT_EQ(
911 kInterFrameDelayMs,
912 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
913 } else {
914 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
915 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
916 EXPECT_EQ(kInterFrameDelayMs,
917 metrics::MinSample("WebRTC.Video.InterframeDelayInMs"));
918 EXPECT_EQ(kInterFrameDelayMs,
919 metrics::MinSample("WebRTC.Video.InterframeDelayMaxInMs"));
920 }
921}
922
ilnik6d5b4d62017-08-30 03:32:14 -0700923TEST_P(ReceiveStatisticsProxyTest, StatsAreSlicedOnSimulcastAndExperiment) {
924 VideoContentType content_type = GetParam();
925 const uint8_t experiment_id = 1;
926 videocontenttypehelpers::SetExperimentId(&content_type, experiment_id);
927 const int kInterFrameDelayMs1 = 30;
928 const int kInterFrameDelayMs2 = 50;
929
930 videocontenttypehelpers::SetSimulcastId(&content_type, 1);
931 for (int i = 0; i <= kMinRequiredSamples; ++i) {
932 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs1);
933 statistics_proxy_->OnDecodedFrame(rtc::Optional<uint8_t>(), content_type);
934 }
935
936 videocontenttypehelpers::SetSimulcastId(&content_type, 2);
937 for (int i = 0; i <= kMinRequiredSamples; ++i) {
938 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs2);
939 statistics_proxy_->OnDecodedFrame(rtc::Optional<uint8_t>(), content_type);
940 }
941 statistics_proxy_.reset();
942
943 if (videocontenttypehelpers::IsScreenshare(content_type)) {
944 EXPECT_EQ(
945 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"));
946 EXPECT_EQ(1, metrics::NumSamples(
947 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
948 EXPECT_EQ(1, metrics::NumSamples(
949 "WebRTC.Video.Screenshare.InterframeDelayInMs.S0"));
950 EXPECT_EQ(1, metrics::NumSamples(
951 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs.S0"));
952 EXPECT_EQ(1, metrics::NumSamples(
953 "WebRTC.Video.Screenshare.InterframeDelayInMs.S1"));
954 EXPECT_EQ(1, metrics::NumSamples(
955 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs.S1"));
956 EXPECT_EQ(1,
957 metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"
958 ".ExperimentGroup0"));
959 EXPECT_EQ(
960 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"
961 ".ExperimentGroup0"));
962 EXPECT_EQ(
963 kInterFrameDelayMs1,
964 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs.S0"));
965 EXPECT_EQ(
966 kInterFrameDelayMs2,
967 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs.S1"));
968 EXPECT_EQ(
969 (kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
970 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs"));
971 EXPECT_EQ(
972 kInterFrameDelayMs2,
973 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
974 EXPECT_EQ(
975 (kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
976 metrics::MinSample(
977 "WebRTC.Video.Screenshare.InterframeDelayInMs.ExperimentGroup0"));
978 } else {
979 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
980 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
981 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs.S0"));
982 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs.S0"));
983 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs.S1"));
984 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs.S1"));
985 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"
986 ".ExperimentGroup0"));
987 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"
988 ".ExperimentGroup0"));
989 EXPECT_EQ(kInterFrameDelayMs1,
990 metrics::MinSample("WebRTC.Video.InterframeDelayInMs.S0"));
991 EXPECT_EQ(kInterFrameDelayMs2,
992 metrics::MinSample("WebRTC.Video.InterframeDelayInMs.S1"));
993 EXPECT_EQ((kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
994 metrics::MinSample("WebRTC.Video.InterframeDelayInMs"));
995 EXPECT_EQ(kInterFrameDelayMs2,
996 metrics::MinSample("WebRTC.Video.InterframeDelayMaxInMs"));
997 EXPECT_EQ((kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
998 metrics::MinSample(
999 "WebRTC.Video.InterframeDelayInMs.ExperimentGroup0"));
1000 }
1001}
sakale5ba44e2016-10-26 07:09:24 -07001002} // namespace webrtc