1 /*
2 * Copyright (c) 2017 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 "modules/audio_coding/neteq/statistics_calculator.h"
12
13 #include "test/gtest.h"
14
15 namespace webrtc {
16
TEST(LifetimeStatistics,TotalSamplesReceived)17 TEST(LifetimeStatistics, TotalSamplesReceived) {
18 StatisticsCalculator stats;
19 for (int i = 0; i < 10; ++i) {
20 stats.IncreaseCounter(480, 48000); // 10 ms at 48 kHz.
21 }
22 EXPECT_EQ(10 * 480u, stats.GetLifetimeStatistics().total_samples_received);
23 }
24
TEST(LifetimeStatistics,SamplesConcealed)25 TEST(LifetimeStatistics, SamplesConcealed) {
26 StatisticsCalculator stats;
27 stats.ExpandedVoiceSamples(100, false);
28 stats.ExpandedNoiseSamples(17, false);
29 EXPECT_EQ(100u + 17u, stats.GetLifetimeStatistics().concealed_samples);
30 }
31
32 // This test verifies that a negative correction of concealed_samples does not
33 // result in a decrease in the stats value (because stats-consuming applications
34 // would not expect the value to decrease). Instead, the correction should be
35 // made to future increments to the stat.
TEST(LifetimeStatistics,SamplesConcealedCorrection)36 TEST(LifetimeStatistics, SamplesConcealedCorrection) {
37 StatisticsCalculator stats;
38 stats.ExpandedVoiceSamples(100, false);
39 EXPECT_EQ(100u, stats.GetLifetimeStatistics().concealed_samples);
40 stats.ExpandedVoiceSamplesCorrection(-10);
41 // Do not subtract directly, but keep the correction for later.
42 EXPECT_EQ(100u, stats.GetLifetimeStatistics().concealed_samples);
43 stats.ExpandedVoiceSamplesCorrection(20);
44 // The total correction is 20 - 10.
45 EXPECT_EQ(110u, stats.GetLifetimeStatistics().concealed_samples);
46
47 // Also test correction done to the next ExpandedVoiceSamples call.
48 stats.ExpandedVoiceSamplesCorrection(-17);
49 EXPECT_EQ(110u, stats.GetLifetimeStatistics().concealed_samples);
50 stats.ExpandedVoiceSamples(100, false);
51 EXPECT_EQ(110u + 100u - 17u, stats.GetLifetimeStatistics().concealed_samples);
52 }
53
54 // This test verifies that neither "accelerate" nor "pre-emptive expand" reults
55 // in a modification to concealed_samples stats. Only PLC operations (i.e.,
56 // "expand" and "merge") should affect the stat.
TEST(LifetimeStatistics,NoUpdateOnTimeStretch)57 TEST(LifetimeStatistics, NoUpdateOnTimeStretch) {
58 StatisticsCalculator stats;
59 stats.ExpandedVoiceSamples(100, false);
60 stats.AcceleratedSamples(4711);
61 stats.PreemptiveExpandedSamples(17);
62 stats.ExpandedVoiceSamples(100, false);
63 EXPECT_EQ(200u, stats.GetLifetimeStatistics().concealed_samples);
64 }
65
TEST(StatisticsCalculator,ExpandedSamplesCorrection)66 TEST(StatisticsCalculator, ExpandedSamplesCorrection) {
67 StatisticsCalculator stats;
68 NetEqNetworkStatistics stats_output;
69 constexpr int kSampleRateHz = 48000;
70 constexpr int k10MsSamples = kSampleRateHz / 100;
71 constexpr int kPacketSizeMs = 20;
72 constexpr size_t kSamplesPerPacket = kPacketSizeMs * kSampleRateHz / 1000;
73 // Assume 2 packets in the buffer.
74 constexpr size_t kNumSamplesInBuffer = 2 * kSamplesPerPacket;
75
76 // Advance time by 10 ms.
77 stats.IncreaseCounter(k10MsSamples, kSampleRateHz);
78
79 stats.GetNetworkStatistics(kSampleRateHz, kNumSamplesInBuffer,
80 kSamplesPerPacket, &stats_output);
81
82 EXPECT_EQ(0u, stats_output.expand_rate);
83 EXPECT_EQ(0u, stats_output.speech_expand_rate);
84
85 // Correct with a negative value.
86 stats.ExpandedVoiceSamplesCorrection(-100);
87 stats.ExpandedNoiseSamplesCorrection(-100);
88 stats.IncreaseCounter(k10MsSamples, kSampleRateHz);
89 stats.GetNetworkStatistics(kSampleRateHz, kNumSamplesInBuffer,
90 kSamplesPerPacket, &stats_output);
91 // Expect no change, since negative values are disallowed.
92 EXPECT_EQ(0u, stats_output.expand_rate);
93 EXPECT_EQ(0u, stats_output.speech_expand_rate);
94
95 // Correct with a positive value.
96 stats.ExpandedVoiceSamplesCorrection(50);
97 stats.ExpandedNoiseSamplesCorrection(200);
98 stats.IncreaseCounter(k10MsSamples, kSampleRateHz);
99 stats.GetNetworkStatistics(kSampleRateHz, kNumSamplesInBuffer,
100 kSamplesPerPacket, &stats_output);
101 // Calculate expected rates in Q14. Expand rate is noise + voice, while
102 // speech expand rate is only voice.
103 EXPECT_EQ(((50u + 200u) << 14) / k10MsSamples, stats_output.expand_rate);
104 EXPECT_EQ((50u << 14) / k10MsSamples, stats_output.speech_expand_rate);
105 }
106
TEST(StatisticsCalculator,RelativePacketArrivalDelay)107 TEST(StatisticsCalculator, RelativePacketArrivalDelay) {
108 StatisticsCalculator stats;
109
110 stats.RelativePacketArrivalDelay(50);
111 NetEqLifetimeStatistics stats_output = stats.GetLifetimeStatistics();
112 EXPECT_EQ(50u, stats_output.relative_packet_arrival_delay_ms);
113
114 stats.RelativePacketArrivalDelay(20);
115 stats_output = stats.GetLifetimeStatistics();
116 EXPECT_EQ(70u, stats_output.relative_packet_arrival_delay_ms);
117 }
118
TEST(StatisticsCalculator,ReceivedPacket)119 TEST(StatisticsCalculator, ReceivedPacket) {
120 StatisticsCalculator stats;
121
122 stats.ReceivedPacket();
123 NetEqLifetimeStatistics stats_output = stats.GetLifetimeStatistics();
124 EXPECT_EQ(1u, stats_output.jitter_buffer_packets_received);
125
126 stats.ReceivedPacket();
127 stats_output = stats.GetLifetimeStatistics();
128 EXPECT_EQ(2u, stats_output.jitter_buffer_packets_received);
129 }
130
TEST(StatisticsCalculator,InterruptionCounter)131 TEST(StatisticsCalculator, InterruptionCounter) {
132 constexpr int fs_khz = 48;
133 constexpr int fs_hz = fs_khz * 1000;
134 StatisticsCalculator stats;
135 stats.DecodedOutputPlayed();
136 stats.EndExpandEvent(fs_hz);
137 auto lts = stats.GetLifetimeStatistics();
138 EXPECT_EQ(0, lts.interruption_count);
139 EXPECT_EQ(0, lts.total_interruption_duration_ms);
140
141 // Add an event that is shorter than 150 ms. Should not be logged.
142 stats.ExpandedVoiceSamples(10 * fs_khz, false); // 10 ms.
143 stats.ExpandedNoiseSamples(139 * fs_khz, false); // 139 ms.
144 stats.EndExpandEvent(fs_hz);
145 lts = stats.GetLifetimeStatistics();
146 EXPECT_EQ(0, lts.interruption_count);
147
148 // Add an event that is longer than 150 ms. Should be logged.
149 stats.ExpandedVoiceSamples(140 * fs_khz, false); // 140 ms.
150 stats.ExpandedNoiseSamples(11 * fs_khz, false); // 11 ms.
151 stats.EndExpandEvent(fs_hz);
152 lts = stats.GetLifetimeStatistics();
153 EXPECT_EQ(1, lts.interruption_count);
154 EXPECT_EQ(151, lts.total_interruption_duration_ms);
155
156 // Add one more long event.
157 stats.ExpandedVoiceSamples(100 * fs_khz, false); // 100 ms.
158 stats.ExpandedNoiseSamples(5000 * fs_khz, false); // 5000 ms.
159 stats.EndExpandEvent(fs_hz);
160 lts = stats.GetLifetimeStatistics();
161 EXPECT_EQ(2, lts.interruption_count);
162 EXPECT_EQ(5100 + 151, lts.total_interruption_duration_ms);
163 }
164
TEST(StatisticsCalculator,InterruptionCounterDoNotLogBeforeDecoding)165 TEST(StatisticsCalculator, InterruptionCounterDoNotLogBeforeDecoding) {
166 constexpr int fs_khz = 48;
167 constexpr int fs_hz = fs_khz * 1000;
168 StatisticsCalculator stats;
169
170 // Add an event that is longer than 150 ms. Should normally be logged, but we
171 // have not called DecodedOutputPlayed() yet, so it shouldn't this time.
172 stats.ExpandedVoiceSamples(151 * fs_khz, false); // 151 ms.
173 stats.EndExpandEvent(fs_hz);
174 auto lts = stats.GetLifetimeStatistics();
175 EXPECT_EQ(0, lts.interruption_count);
176
177 // Call DecodedOutputPlayed(). Logging should happen after this.
178 stats.DecodedOutputPlayed();
179
180 // Add one more long event.
181 stats.ExpandedVoiceSamples(151 * fs_khz, false); // 151 ms.
182 stats.EndExpandEvent(fs_hz);
183 lts = stats.GetLifetimeStatistics();
184 EXPECT_EQ(1, lts.interruption_count);
185 }
186
187 } // namespace webrtc
188