blob: 2c4d3301950c40d952a4cba08827b6148184ecdd [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
11#include "webrtc/video/receive_statistics_proxy.h"
12
asapersson2077f2f2017-05-11 05:37:35 -070013#include <limits>
sakale5ba44e2016-10-26 07:09:24 -070014#include <memory>
15
nissef93752a2017-05-10 05:25:59 -070016#include "webrtc/api/video/i420_buffer.h"
hbos50cfe1f2017-01-23 07:21:55 -080017#include "webrtc/api/video/video_frame.h"
18#include "webrtc/api/video/video_rotation.h"
asapersson6966bd52017-01-03 00:44:06 -080019#include "webrtc/modules/video_coding/include/video_codec_interface.h"
asapersson0c43f772016-11-30 01:42:26 -080020#include "webrtc/system_wrappers/include/metrics.h"
asaperssonde9e5ff2016-11-02 07:14:03 -070021#include "webrtc/system_wrappers/include/metrics_default.h"
sakale5ba44e2016-10-26 07:09:24 -070022#include "webrtc/test/gtest.h"
23
24namespace webrtc {
asaperssonde9e5ff2016-11-02 07:14:03 -070025namespace {
26const int64_t kFreqOffsetProcessIntervalInMs = 40000;
asapersson46c4e3c2016-11-03 06:48:19 -070027const uint32_t kLocalSsrc = 123;
28const uint32_t kRemoteSsrc = 456;
29const int kMinRequiredSamples = 200;
asaperssonde9e5ff2016-11-02 07:14:03 -070030} // namespace
sakale5ba44e2016-10-26 07:09:24 -070031
32// TODO(sakal): ReceiveStatisticsProxy is lacking unittesting.
33class ReceiveStatisticsProxyTest : public ::testing::Test {
34 public:
35 ReceiveStatisticsProxyTest() : fake_clock_(1234), config_(GetTestConfig()) {}
36 virtual ~ReceiveStatisticsProxyTest() {}
37
38 protected:
39 virtual void SetUp() {
asaperssonde9e5ff2016-11-02 07:14:03 -070040 metrics::Reset();
sakale5ba44e2016-10-26 07:09:24 -070041 statistics_proxy_.reset(new ReceiveStatisticsProxy(&config_, &fake_clock_));
42 }
43
44 VideoReceiveStream::Config GetTestConfig() {
45 VideoReceiveStream::Config config(nullptr);
asapersson46c4e3c2016-11-03 06:48:19 -070046 config.rtp.local_ssrc = kLocalSsrc;
47 config.rtp.remote_ssrc = kRemoteSsrc;
sakale5ba44e2016-10-26 07:09:24 -070048 return config;
49 }
50
asapersson2077f2f2017-05-11 05:37:35 -070051 void InsertFirstRtpPacket(uint32_t ssrc) {
52 StreamDataCounters counters;
53 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
54 statistics_proxy_->DataCountersUpdated(counters, ssrc);
55 }
56
57 VideoFrame CreateFrame(int width, int height) {
58 VideoFrame frame(I420Buffer::Create(width, height), 0, 0, kVideoRotation_0);
59 frame.set_ntp_time_ms(fake_clock_.CurrentNtpInMilliseconds());
60 return frame;
61 }
62
sakale5ba44e2016-10-26 07:09:24 -070063 SimulatedClock fake_clock_;
asaperssonde9e5ff2016-11-02 07:14:03 -070064 const VideoReceiveStream::Config config_;
sakale5ba44e2016-10-26 07:09:24 -070065 std::unique_ptr<ReceiveStatisticsProxy> statistics_proxy_;
sakale5ba44e2016-10-26 07:09:24 -070066};
67
68TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameIncreasesFramesDecoded) {
69 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_decoded);
70 for (uint32_t i = 1; i <= 3; ++i) {
ilnik00d802b2017-04-11 10:34:31 -070071 statistics_proxy_->OnDecodedFrame(rtc::Optional<uint8_t>(),
72 VideoContentType::UNSPECIFIED);
sakale5ba44e2016-10-26 07:09:24 -070073 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_decoded);
74 }
75}
76
sakalcc452e12017-02-09 04:53:45 -080077TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameWithQpResetsFramesDecoded) {
78 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_decoded);
79 for (uint32_t i = 1; i <= 3; ++i) {
ilnik00d802b2017-04-11 10:34:31 -070080 statistics_proxy_->OnDecodedFrame(rtc::Optional<uint8_t>(),
81 VideoContentType::UNSPECIFIED);
sakalcc452e12017-02-09 04:53:45 -080082 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_decoded);
83 }
ilnik00d802b2017-04-11 10:34:31 -070084 statistics_proxy_->OnDecodedFrame(rtc::Optional<uint8_t>(1u),
85 VideoContentType::UNSPECIFIED);
sakalcc452e12017-02-09 04:53:45 -080086 EXPECT_EQ(1u, statistics_proxy_->GetStats().frames_decoded);
87}
88
89TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameIncreasesQpSum) {
90 EXPECT_EQ(rtc::Optional<uint64_t>(), statistics_proxy_->GetStats().qp_sum);
ilnik00d802b2017-04-11 10:34:31 -070091 statistics_proxy_->OnDecodedFrame(rtc::Optional<uint8_t>(3u),
92 VideoContentType::UNSPECIFIED);
sakalcc452e12017-02-09 04:53:45 -080093 EXPECT_EQ(rtc::Optional<uint64_t>(3u), statistics_proxy_->GetStats().qp_sum);
ilnik00d802b2017-04-11 10:34:31 -070094 statistics_proxy_->OnDecodedFrame(rtc::Optional<uint8_t>(127u),
95 VideoContentType::UNSPECIFIED);
sakalcc452e12017-02-09 04:53:45 -080096 EXPECT_EQ(rtc::Optional<uint64_t>(130u),
97 statistics_proxy_->GetStats().qp_sum);
98}
99
100TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameWithoutQpQpSumWontExist) {
101 EXPECT_EQ(rtc::Optional<uint64_t>(), statistics_proxy_->GetStats().qp_sum);
ilnik00d802b2017-04-11 10:34:31 -0700102 statistics_proxy_->OnDecodedFrame(rtc::Optional<uint8_t>(),
103 VideoContentType::UNSPECIFIED);
sakalcc452e12017-02-09 04:53:45 -0800104 EXPECT_EQ(rtc::Optional<uint64_t>(), statistics_proxy_->GetStats().qp_sum);
105}
106
107TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameWithoutQpResetsQpSum) {
108 EXPECT_EQ(rtc::Optional<uint64_t>(), statistics_proxy_->GetStats().qp_sum);
ilnik00d802b2017-04-11 10:34:31 -0700109 statistics_proxy_->OnDecodedFrame(rtc::Optional<uint8_t>(3u),
110 VideoContentType::UNSPECIFIED);
sakalcc452e12017-02-09 04:53:45 -0800111 EXPECT_EQ(rtc::Optional<uint64_t>(3u), statistics_proxy_->GetStats().qp_sum);
ilnik00d802b2017-04-11 10:34:31 -0700112 statistics_proxy_->OnDecodedFrame(rtc::Optional<uint8_t>(),
113 VideoContentType::UNSPECIFIED);
sakalcc452e12017-02-09 04:53:45 -0800114 EXPECT_EQ(rtc::Optional<uint64_t>(), statistics_proxy_->GetStats().qp_sum);
115}
116
hbos50cfe1f2017-01-23 07:21:55 -0800117TEST_F(ReceiveStatisticsProxyTest, OnRenderedFrameIncreasesFramesRendered) {
118 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_rendered);
ilnik00d802b2017-04-11 10:34:31 -0700119 webrtc::VideoFrame frame(webrtc::I420Buffer::Create(1, 1), 0, 0,
120 webrtc::kVideoRotation_0);
hbos50cfe1f2017-01-23 07:21:55 -0800121 for (uint32_t i = 1; i <= 3; ++i) {
122 statistics_proxy_->OnRenderedFrame(frame);
123 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_rendered);
124 }
125}
126
asapersson46c4e3c2016-11-03 06:48:19 -0700127TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsSsrc) {
128 EXPECT_EQ(kRemoteSsrc, statistics_proxy_->GetStats().ssrc);
129}
130
131TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsIncomingPayloadType) {
132 const int kPayloadType = 111;
133 statistics_proxy_->OnIncomingPayloadType(kPayloadType);
134 EXPECT_EQ(kPayloadType, statistics_proxy_->GetStats().current_payload_type);
135}
136
asapersson6966bd52017-01-03 00:44:06 -0800137TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsDecoderImplementationName) {
138 const char* kName = "decoderName";
139 statistics_proxy_->OnDecoderImplementationName(kName);
140 EXPECT_STREQ(
141 kName, statistics_proxy_->GetStats().decoder_implementation_name.c_str());
142}
143
philipela45102f2017-02-22 05:30:39 -0800144TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsOnCompleteFrame) {
145 const int kFrameSizeBytes = 1000;
146 statistics_proxy_->OnCompleteFrame(true, kFrameSizeBytes);
147 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
148 EXPECT_EQ(1, stats.network_frame_rate);
philipela45102f2017-02-22 05:30:39 -0800149 EXPECT_EQ(1, stats.frame_counts.key_frames);
150 EXPECT_EQ(0, stats.frame_counts.delta_frames);
asapersson46c4e3c2016-11-03 06:48:19 -0700151}
152
153TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsDecodeTimingStats) {
154 const int kDecodeMs = 1;
155 const int kMaxDecodeMs = 2;
156 const int kCurrentDelayMs = 3;
157 const int kTargetDelayMs = 4;
158 const int kJitterBufferMs = 5;
159 const int kMinPlayoutDelayMs = 6;
160 const int kRenderDelayMs = 7;
161 const int64_t kRttMs = 8;
philipela45102f2017-02-22 05:30:39 -0800162 statistics_proxy_->OnRttUpdate(kRttMs, 0);
163 statistics_proxy_->OnFrameBufferTimingsUpdated(
asapersson46c4e3c2016-11-03 06:48:19 -0700164 kDecodeMs, kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs, kJitterBufferMs,
philipela45102f2017-02-22 05:30:39 -0800165 kMinPlayoutDelayMs, kRenderDelayMs);
asapersson46c4e3c2016-11-03 06:48:19 -0700166 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
167 EXPECT_EQ(kDecodeMs, stats.decode_ms);
168 EXPECT_EQ(kMaxDecodeMs, stats.max_decode_ms);
169 EXPECT_EQ(kCurrentDelayMs, stats.current_delay_ms);
170 EXPECT_EQ(kTargetDelayMs, stats.target_delay_ms);
171 EXPECT_EQ(kJitterBufferMs, stats.jitter_buffer_ms);
172 EXPECT_EQ(kMinPlayoutDelayMs, stats.min_playout_delay_ms);
173 EXPECT_EQ(kRenderDelayMs, stats.render_delay_ms);
174}
175
asapersson6966bd52017-01-03 00:44:06 -0800176TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsRtcpPacketTypeCounts) {
177 const uint32_t kFirPackets = 33;
178 const uint32_t kPliPackets = 44;
179 const uint32_t kNackPackets = 55;
180 RtcpPacketTypeCounter counter;
181 counter.fir_packets = kFirPackets;
182 counter.pli_packets = kPliPackets;
183 counter.nack_packets = kNackPackets;
184 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc, counter);
185 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
186 EXPECT_EQ(kFirPackets, stats.rtcp_packet_type_counts.fir_packets);
187 EXPECT_EQ(kPliPackets, stats.rtcp_packet_type_counts.pli_packets);
188 EXPECT_EQ(kNackPackets, stats.rtcp_packet_type_counts.nack_packets);
189}
190
191TEST_F(ReceiveStatisticsProxyTest,
192 GetStatsReportsNoRtcpPacketTypeCountsForUnknownSsrc) {
193 RtcpPacketTypeCounter counter;
194 counter.fir_packets = 33;
195 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc + 1, counter);
196 EXPECT_EQ(0u,
197 statistics_proxy_->GetStats().rtcp_packet_type_counts.fir_packets);
198}
199
200TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsFrameCounts) {
201 const int kKeyFrames = 3;
202 const int kDeltaFrames = 22;
203 FrameCounts frame_counts;
204 frame_counts.key_frames = kKeyFrames;
205 frame_counts.delta_frames = kDeltaFrames;
206 statistics_proxy_->OnFrameCountsUpdated(frame_counts);
207 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
208 EXPECT_EQ(kKeyFrames, stats.frame_counts.key_frames);
209 EXPECT_EQ(kDeltaFrames, stats.frame_counts.delta_frames);
210}
211
asapersson46c4e3c2016-11-03 06:48:19 -0700212TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsDiscardedPackets) {
213 const int kDiscardedPackets = 12;
214 statistics_proxy_->OnDiscardedPacketsUpdated(kDiscardedPackets);
215 EXPECT_EQ(kDiscardedPackets, statistics_proxy_->GetStats().discarded_packets);
216}
217
asapersson6966bd52017-01-03 00:44:06 -0800218TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsRtcpStats) {
219 const uint8_t kFracLost = 0;
220 const uint32_t kCumLost = 1;
221 const uint32_t kExtSeqNum = 10;
222 const uint32_t kJitter = 4;
223
224 RtcpStatistics rtcp_stats;
225 rtcp_stats.fraction_lost = kFracLost;
226 rtcp_stats.cumulative_lost = kCumLost;
227 rtcp_stats.extended_max_sequence_number = kExtSeqNum;
228 rtcp_stats.jitter = kJitter;
229 statistics_proxy_->StatisticsUpdated(rtcp_stats, kRemoteSsrc);
230
231 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
232 EXPECT_EQ(kFracLost, stats.rtcp_stats.fraction_lost);
233 EXPECT_EQ(kCumLost, stats.rtcp_stats.cumulative_lost);
234 EXPECT_EQ(kExtSeqNum, stats.rtcp_stats.extended_max_sequence_number);
235 EXPECT_EQ(kJitter, stats.rtcp_stats.jitter);
236}
237
238TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsCName) {
239 const char* kName = "cName";
240 statistics_proxy_->CNameChanged(kName, kRemoteSsrc);
241 EXPECT_STREQ(kName, statistics_proxy_->GetStats().c_name.c_str());
242}
243
244TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsNoCNameForUnknownSsrc) {
245 const char* kName = "cName";
246 statistics_proxy_->CNameChanged(kName, kRemoteSsrc + 1);
247 EXPECT_STREQ("", statistics_proxy_->GetStats().c_name.c_str());
248}
249
ilnik2edc6842017-07-06 03:06:50 -0700250TEST_F(ReceiveStatisticsProxyTest,
251 GetTimingFrameInfoReportsLongestTimingFrame) {
252 const int64_t kShortEndToEndDelay = 10;
253 const int64_t kMedEndToEndDelay = 20;
254 const int64_t kLongEndToEndDelay = 100;
255 const uint32_t kExpectedRtpTimestamp = 2;
256 TimingFrameInfo info;
257 rtc::Optional<TimingFrameInfo> result;
258 info.rtp_timestamp = kExpectedRtpTimestamp - 1;
259 info.capture_time_ms = 0;
260 info.decode_finish_ms = kShortEndToEndDelay;
261 statistics_proxy_->OnTimingFrameInfoUpdated(info);
262 info.rtp_timestamp =
263 kExpectedRtpTimestamp; // this frame should be reported in the end.
264 info.capture_time_ms = 0;
265 info.decode_finish_ms = kLongEndToEndDelay;
266 statistics_proxy_->OnTimingFrameInfoUpdated(info);
267 info.rtp_timestamp = kExpectedRtpTimestamp + 1;
268 info.capture_time_ms = 0;
269 info.decode_finish_ms = kMedEndToEndDelay;
270 statistics_proxy_->OnTimingFrameInfoUpdated(info);
271 result = statistics_proxy_->GetAndResetTimingFrameInfo();
272 EXPECT_TRUE(result);
273 EXPECT_EQ(kExpectedRtpTimestamp, result->rtp_timestamp);
274}
275
276TEST_F(ReceiveStatisticsProxyTest, GetTimingFrameInfoTimingFramesReportedOnce) {
277 const int64_t kShortEndToEndDelay = 10;
278 const uint32_t kExpectedRtpTimestamp = 2;
279 TimingFrameInfo info;
280 rtc::Optional<TimingFrameInfo> result;
281 info.rtp_timestamp = kExpectedRtpTimestamp;
282 info.capture_time_ms = 0;
283 info.decode_finish_ms = kShortEndToEndDelay;
284 statistics_proxy_->OnTimingFrameInfoUpdated(info);
285 result = statistics_proxy_->GetAndResetTimingFrameInfo();
286 EXPECT_TRUE(result);
287 EXPECT_EQ(kExpectedRtpTimestamp, result->rtp_timestamp);
288 result = statistics_proxy_->GetAndResetTimingFrameInfo();
289 EXPECT_FALSE(result);
290}
291
asapersson46c4e3c2016-11-03 06:48:19 -0700292TEST_F(ReceiveStatisticsProxyTest, LifetimeHistogramIsUpdated) {
293 const int64_t kTimeSec = 3;
294 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
295 // Histograms are updated when the statistics_proxy_ is deleted.
296 statistics_proxy_.reset();
297 EXPECT_EQ(1,
298 metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
299 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.ReceiveStreamLifetimeInSeconds",
300 kTimeSec));
301}
302
palmkvista40672a2017-01-13 05:58:34 -0800303TEST_F(ReceiveStatisticsProxyTest, BadCallHistogramsAreUpdated) {
304 // Based on the tuning parameters this will produce 7 uncertain states,
305 // then 10 certainly bad states. There has to be 10 certain states before
306 // any histograms are recorded.
307 const int kNumBadSamples = 17;
308
309 StreamDataCounters counters;
310 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
311 statistics_proxy_->DataCountersUpdated(counters, config_.rtp.remote_ssrc);
312
313 for (int i = 0; i < kNumBadSamples; ++i) {
314 // Since OnRenderedFrame is never called the fps in each sample will be 0,
315 // i.e. bad
316 fake_clock_.AdvanceTimeMilliseconds(1000);
317 statistics_proxy_->OnIncomingRate(0, 0);
318 }
319 // Histograms are updated when the statistics_proxy_ is deleted.
320 statistics_proxy_.reset();
321 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BadCall.Any"));
322 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BadCall.Any", 100));
323
324 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BadCall.FrameRate"));
325 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BadCall.FrameRate", 100));
326
327 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.BadCall.FrameRateVariance"));
328
329 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.BadCall.Qp"));
330}
331
asapersson0c43f772016-11-30 01:42:26 -0800332TEST_F(ReceiveStatisticsProxyTest, PacketLossHistogramIsUpdated) {
333 const uint32_t kCumLost1 = 1;
334 const uint32_t kExtSeqNum1 = 10;
335 const uint32_t kCumLost2 = 2;
336 const uint32_t kExtSeqNum2 = 20;
337
338 // One report block received.
339 RtcpStatistics rtcp_stats1;
340 rtcp_stats1.cumulative_lost = kCumLost1;
341 rtcp_stats1.extended_max_sequence_number = kExtSeqNum1;
342 statistics_proxy_->StatisticsUpdated(rtcp_stats1, kRemoteSsrc);
343
344 // Two report blocks received.
345 RtcpStatistics rtcp_stats2;
346 rtcp_stats2.cumulative_lost = kCumLost2;
347 rtcp_stats2.extended_max_sequence_number = kExtSeqNum2;
348 statistics_proxy_->StatisticsUpdated(rtcp_stats2, kRemoteSsrc);
349
350 // Two received report blocks but min run time has not passed.
351 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
352 SetUp(); // Reset stat proxy causes histograms to be updated.
353 EXPECT_EQ(0,
354 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
355
356 // Two report blocks received.
357 statistics_proxy_->StatisticsUpdated(rtcp_stats1, kRemoteSsrc);
358 statistics_proxy_->StatisticsUpdated(rtcp_stats2, kRemoteSsrc);
359
360 // Two received report blocks and min run time has passed.
361 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
362 SetUp();
363 EXPECT_EQ(1,
364 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
365 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.ReceivedPacketsLostInPercent",
366 (kCumLost2 - kCumLost1) * 100 /
367 (kExtSeqNum2 - kExtSeqNum1)));
368}
369
370TEST_F(ReceiveStatisticsProxyTest,
371 PacketLossHistogramIsNotUpdatedIfLessThanTwoReportBlocksAreReceived) {
372 RtcpStatistics rtcp_stats1;
373 rtcp_stats1.cumulative_lost = 1;
374 rtcp_stats1.extended_max_sequence_number = 10;
375
376 // Min run time has passed but no received report block.
377 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
378 SetUp(); // Reset stat proxy causes histograms to be updated.
379 EXPECT_EQ(0,
380 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
381
382 // Min run time has passed but only one received report block.
383 statistics_proxy_->StatisticsUpdated(rtcp_stats1, kRemoteSsrc);
384 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
385 SetUp();
386 EXPECT_EQ(0,
387 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
388}
389
asapersson2077f2f2017-05-11 05:37:35 -0700390TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsAvSyncOffset) {
391 const int64_t kSyncOffsetMs = 22;
392 const double kFreqKhz = 90.0;
393 EXPECT_EQ(std::numeric_limits<int>::max(),
394 statistics_proxy_->GetStats().sync_offset_ms);
395 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
396 EXPECT_EQ(kSyncOffsetMs, statistics_proxy_->GetStats().sync_offset_ms);
397}
398
asapersson46c4e3c2016-11-03 06:48:19 -0700399TEST_F(ReceiveStatisticsProxyTest, AvSyncOffsetHistogramIsUpdated) {
400 const int64_t kSyncOffsetMs = 22;
401 const double kFreqKhz = 90.0;
402 for (int i = 0; i < kMinRequiredSamples; ++i)
403 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
404 // Histograms are updated when the statistics_proxy_ is deleted.
405 statistics_proxy_.reset();
406 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AVSyncOffsetInMs"));
407 EXPECT_EQ(1,
408 metrics::NumEvents("WebRTC.Video.AVSyncOffsetInMs", kSyncOffsetMs));
409}
410
asaperssonde9e5ff2016-11-02 07:14:03 -0700411TEST_F(ReceiveStatisticsProxyTest, RtpToNtpFrequencyOffsetHistogramIsUpdated) {
412 const int64_t kSyncOffsetMs = 22;
413 const double kFreqKhz = 90.0;
414 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
415 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz + 2.2);
416 fake_clock_.AdvanceTimeMilliseconds(kFreqOffsetProcessIntervalInMs);
417 // Process interval passed, max diff: 2.
418 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz + 1.1);
419 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz - 4.2);
420 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz - 0.9);
421 fake_clock_.AdvanceTimeMilliseconds(kFreqOffsetProcessIntervalInMs);
422 // Process interval passed, max diff: 4.
423 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
424 statistics_proxy_.reset();
425 // Average reported: (2 + 4) / 2 = 3.
426 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtpToNtpFreqOffsetInKhz"));
427 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtpToNtpFreqOffsetInKhz", 3));
428}
429
asapersson6966bd52017-01-03 00:44:06 -0800430TEST_F(ReceiveStatisticsProxyTest, Vp8QpHistogramIsUpdated) {
431 const int kQp = 22;
432 EncodedImage encoded_image;
433 encoded_image.qp_ = kQp;
434 CodecSpecificInfo codec_info;
435 codec_info.codecType = kVideoCodecVP8;
436
437 for (int i = 0; i < kMinRequiredSamples; ++i)
438 statistics_proxy_->OnPreDecode(encoded_image, &codec_info);
439
440 statistics_proxy_.reset();
441 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
442 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Decoded.Vp8.Qp", kQp));
443}
444
445TEST_F(ReceiveStatisticsProxyTest, Vp8QpHistogramIsNotUpdatedForTooFewSamples) {
446 EncodedImage encoded_image;
447 encoded_image.qp_ = 22;
448 CodecSpecificInfo codec_info;
449 codec_info.codecType = kVideoCodecVP8;
450
451 for (int i = 0; i < kMinRequiredSamples - 1; ++i)
452 statistics_proxy_->OnPreDecode(encoded_image, &codec_info);
453
454 statistics_proxy_.reset();
455 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
456}
457
458TEST_F(ReceiveStatisticsProxyTest, Vp8QpHistogramIsNotUpdatedIfNoQpValue) {
459 EncodedImage encoded_image;
460 CodecSpecificInfo codec_info;
461 codec_info.codecType = kVideoCodecVP8;
462
463 for (int i = 0; i < kMinRequiredSamples; ++i)
464 statistics_proxy_->OnPreDecode(encoded_image, &codec_info);
465
466 statistics_proxy_.reset();
467 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
468}
469
asaperssonb99baf82017-04-20 04:05:43 -0700470TEST_F(ReceiveStatisticsProxyTest,
471 KeyFrameHistogramNotUpdatedForTooFewSamples) {
472 const bool kIsKeyFrame = false;
473 const int kFrameSizeBytes = 1000;
474
475 for (int i = 0; i < kMinRequiredSamples - 1; ++i)
476 statistics_proxy_->OnCompleteFrame(kIsKeyFrame, kFrameSizeBytes);
477
478 EXPECT_EQ(0, statistics_proxy_->GetStats().frame_counts.key_frames);
479 EXPECT_EQ(kMinRequiredSamples - 1,
480 statistics_proxy_->GetStats().frame_counts.delta_frames);
481
482 statistics_proxy_.reset();
483 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
484}
485
486TEST_F(ReceiveStatisticsProxyTest,
487 KeyFrameHistogramUpdatedForMinRequiredSamples) {
488 const bool kIsKeyFrame = false;
489 const int kFrameSizeBytes = 1000;
490
491 for (int i = 0; i < kMinRequiredSamples; ++i)
492 statistics_proxy_->OnCompleteFrame(kIsKeyFrame, kFrameSizeBytes);
493
494 EXPECT_EQ(0, statistics_proxy_->GetStats().frame_counts.key_frames);
495 EXPECT_EQ(kMinRequiredSamples,
496 statistics_proxy_->GetStats().frame_counts.delta_frames);
497
498 statistics_proxy_.reset();
499 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
500 EXPECT_EQ(1,
501 metrics::NumEvents("WebRTC.Video.KeyFramesReceivedInPermille", 0));
502}
503
504TEST_F(ReceiveStatisticsProxyTest, KeyFrameHistogramIsUpdated) {
505 const int kFrameSizeBytes = 1000;
506
507 for (int i = 0; i < kMinRequiredSamples; ++i)
508 statistics_proxy_->OnCompleteFrame(true, kFrameSizeBytes);
509
510 for (int i = 0; i < kMinRequiredSamples; ++i)
511 statistics_proxy_->OnCompleteFrame(false, kFrameSizeBytes);
512
513 EXPECT_EQ(kMinRequiredSamples,
514 statistics_proxy_->GetStats().frame_counts.key_frames);
515 EXPECT_EQ(kMinRequiredSamples,
516 statistics_proxy_->GetStats().frame_counts.delta_frames);
517
518 statistics_proxy_.reset();
519 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
520 EXPECT_EQ(
521 1, metrics::NumEvents("WebRTC.Video.KeyFramesReceivedInPermille", 500));
522}
523
524TEST_F(ReceiveStatisticsProxyTest, TimingHistogramsNotUpdatedForTooFewSamples) {
525 const int kDecodeMs = 1;
526 const int kMaxDecodeMs = 2;
527 const int kCurrentDelayMs = 3;
528 const int kTargetDelayMs = 4;
529 const int kJitterBufferMs = 5;
530 const int kMinPlayoutDelayMs = 6;
531 const int kRenderDelayMs = 7;
532
533 for (int i = 0; i < kMinRequiredSamples - 1; ++i) {
534 statistics_proxy_->OnFrameBufferTimingsUpdated(
535 kDecodeMs, kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs,
536 kJitterBufferMs, kMinPlayoutDelayMs, kRenderDelayMs);
537 }
538
539 statistics_proxy_.reset();
540 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
541 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
542 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
543 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
544 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
545}
546
547TEST_F(ReceiveStatisticsProxyTest, TimingHistogramsAreUpdated) {
548 const int kDecodeMs = 1;
549 const int kMaxDecodeMs = 2;
550 const int kCurrentDelayMs = 3;
551 const int kTargetDelayMs = 4;
552 const int kJitterBufferMs = 5;
553 const int kMinPlayoutDelayMs = 6;
554 const int kRenderDelayMs = 7;
555
556 for (int i = 0; i < kMinRequiredSamples; ++i) {
557 statistics_proxy_->OnFrameBufferTimingsUpdated(
558 kDecodeMs, kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs,
559 kJitterBufferMs, kMinPlayoutDelayMs, kRenderDelayMs);
560 }
561
562 statistics_proxy_.reset();
563 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
564 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
565 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
566 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
567 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
568
569 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DecodeTimeInMs", kDecodeMs));
570 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.JitterBufferDelayInMs",
571 kJitterBufferMs));
572 EXPECT_EQ(1,
573 metrics::NumEvents("WebRTC.Video.TargetDelayInMs", kTargetDelayMs));
574 EXPECT_EQ(
575 1, metrics::NumEvents("WebRTC.Video.CurrentDelayInMs", kCurrentDelayMs));
576 EXPECT_EQ(1,
577 metrics::NumEvents("WebRTC.Video.OnewayDelayInMs", kTargetDelayMs));
578}
579
sprang948b2752017-05-04 02:47:13 -0700580TEST_F(ReceiveStatisticsProxyTest, DoesNotReportStaleFramerates) {
581 const int kDefaultFps = 30;
582 const int kWidth = 320;
583 const int kHeight = 240;
584
585 rtc::scoped_refptr<VideoFrameBuffer> video_frame_buffer(
586 I420Buffer::Create(kWidth, kHeight));
587 VideoFrame frame(video_frame_buffer, kVideoRotation_0, 0);
588
589 for (int i = 0; i < kDefaultFps; ++i) {
590 // Since OnRenderedFrame is never called the fps in each sample will be 0,
591 // i.e. bad
592 frame.set_ntp_time_ms(fake_clock_.CurrentNtpInMilliseconds());
593 statistics_proxy_->OnDecodedFrame(rtc::Optional<uint8_t>(),
594 VideoContentType::UNSPECIFIED);
595 statistics_proxy_->OnRenderedFrame(frame);
596 fake_clock_.AdvanceTimeMilliseconds(1000 / kDefaultFps);
597 }
598
599 EXPECT_EQ(kDefaultFps, statistics_proxy_->GetStats().decode_frame_rate);
600 EXPECT_EQ(kDefaultFps, statistics_proxy_->GetStats().render_frame_rate);
601
602 // FPS trackers in stats proxy have a 1000ms sliding window.
603 fake_clock_.AdvanceTimeMilliseconds(1000);
604 EXPECT_EQ(0, statistics_proxy_->GetStats().decode_frame_rate);
605 EXPECT_EQ(0, statistics_proxy_->GetStats().render_frame_rate);
606}
607
asapersson2077f2f2017-05-11 05:37:35 -0700608TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsReceivedFrameStats) {
609 const int kWidth = 160;
610 const int kHeight = 120;
611 EXPECT_EQ(0, statistics_proxy_->GetStats().width);
612 EXPECT_EQ(0, statistics_proxy_->GetStats().height);
613 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_rendered);
614
615 statistics_proxy_->OnRenderedFrame(CreateFrame(kWidth, kHeight));
616
617 EXPECT_EQ(kWidth, statistics_proxy_->GetStats().width);
618 EXPECT_EQ(kHeight, statistics_proxy_->GetStats().height);
619 EXPECT_EQ(1u, statistics_proxy_->GetStats().frames_rendered);
620}
621
622TEST_F(ReceiveStatisticsProxyTest,
623 ReceivedFrameHistogramsAreNotUpdatedForTooFewSamples) {
624 const int kWidth = 160;
625 const int kHeight = 120;
626
627 for (int i = 0; i < kMinRequiredSamples - 1; ++i)
628 statistics_proxy_->OnRenderedFrame(CreateFrame(kWidth, kHeight));
629
630 statistics_proxy_.reset();
631 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
632 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
633 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
634 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
635}
636
637TEST_F(ReceiveStatisticsProxyTest, ReceivedFrameHistogramsAreUpdated) {
638 const int kWidth = 160;
639 const int kHeight = 120;
640
641 for (int i = 0; i < kMinRequiredSamples; ++i)
642 statistics_proxy_->OnRenderedFrame(CreateFrame(kWidth, kHeight));
643
644 statistics_proxy_.reset();
645 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
646 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
647 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
648 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
649 EXPECT_EQ(1,
650 metrics::NumEvents("WebRTC.Video.ReceivedWidthInPixels", kWidth));
651 EXPECT_EQ(1,
652 metrics::NumEvents("WebRTC.Video.ReceivedHeightInPixels", kHeight));
653}
654
655TEST_F(ReceiveStatisticsProxyTest,
656 RtcpHistogramsNotUpdatedIfMinRuntimeHasNotPassed) {
657 InsertFirstRtpPacket(kRemoteSsrc);
658 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000) -
659 1);
660
661 RtcpPacketTypeCounter counter;
662 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc, counter);
663
664 statistics_proxy_.reset();
665 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
666 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
667 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
668}
669
670TEST_F(ReceiveStatisticsProxyTest, RtcpHistogramsAreUpdated) {
671 InsertFirstRtpPacket(kRemoteSsrc);
672 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
673
674 const uint32_t kFirPackets = 100;
675 const uint32_t kPliPackets = 200;
676 const uint32_t kNackPackets = 300;
677
678 RtcpPacketTypeCounter counter;
679 counter.fir_packets = kFirPackets;
680 counter.pli_packets = kPliPackets;
681 counter.nack_packets = kNackPackets;
682 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc, counter);
683
684 statistics_proxy_.reset();
685 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
686 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
687 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
688 EXPECT_EQ(
689 1, metrics::NumEvents("WebRTC.Video.FirPacketsSentPerMinute",
690 kFirPackets * 60 / metrics::kMinRunTimeInSeconds));
691 EXPECT_EQ(
692 1, metrics::NumEvents("WebRTC.Video.PliPacketsSentPerMinute",
693 kPliPackets * 60 / metrics::kMinRunTimeInSeconds));
694 EXPECT_EQ(
695 1, metrics::NumEvents("WebRTC.Video.NackPacketsSentPerMinute",
696 kNackPackets * 60 / metrics::kMinRunTimeInSeconds));
697}
698
sakale5ba44e2016-10-26 07:09:24 -0700699} // namespace webrtc