statistics_calculator_unittest.cc (10585B)
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 <cstddef> 14 15 #include "api/neteq/neteq.h" 16 #include "api/neteq/tick_timer.h" 17 #include "test/gtest.h" 18 19 namespace webrtc { 20 21 TEST(LifetimeStatistics, TotalSamplesReceived) { 22 TickTimer timer; 23 StatisticsCalculator stats(&timer); 24 stats.DecodedOutputPlayed(); 25 for (int i = 0; i < 10; ++i) { 26 stats.IncreaseCounter(480, 48000); // 10 ms at 48 kHz. 27 } 28 EXPECT_EQ(10 * 480u, stats.GetLifetimeStatistics().total_samples_received); 29 } 30 31 TEST(LifetimeStatistics, SamplesConcealed) { 32 TickTimer timer; 33 StatisticsCalculator stats(&timer); 34 stats.DecodedOutputPlayed(); 35 stats.ExpandedVoiceSamples(100, false); 36 stats.ExpandedNoiseSamples(17, false); 37 EXPECT_EQ(100u + 17u, stats.GetLifetimeStatistics().concealed_samples); 38 } 39 40 // This test verifies that a negative correction of concealed_samples does not 41 // result in a decrease in the stats value (because stats-consuming applications 42 // would not expect the value to decrease). Instead, the correction should be 43 // made to future increments to the stat. 44 TEST(LifetimeStatistics, SamplesConcealedCorrection) { 45 TickTimer timer; 46 StatisticsCalculator stats(&timer); 47 stats.DecodedOutputPlayed(); 48 stats.ExpandedVoiceSamples(100, false); 49 EXPECT_EQ(100u, stats.GetLifetimeStatistics().concealed_samples); 50 stats.ExpandedVoiceSamplesCorrection(-10); 51 // Do not subtract directly, but keep the correction for later. 52 EXPECT_EQ(100u, stats.GetLifetimeStatistics().concealed_samples); 53 stats.ExpandedVoiceSamplesCorrection(20); 54 // The total correction is 20 - 10. 55 EXPECT_EQ(110u, stats.GetLifetimeStatistics().concealed_samples); 56 57 // Also test correction done to the next ExpandedVoiceSamples call. 58 stats.ExpandedVoiceSamplesCorrection(-17); 59 EXPECT_EQ(110u, stats.GetLifetimeStatistics().concealed_samples); 60 stats.ExpandedVoiceSamples(100, false); 61 EXPECT_EQ(110u + 100u - 17u, stats.GetLifetimeStatistics().concealed_samples); 62 } 63 64 // This test verifies that neither "accelerate" nor "pre-emptive expand" reults 65 // in a modification to concealed_samples stats. Only PLC operations (i.e., 66 // "expand" and "merge") should affect the stat. 67 TEST(LifetimeStatistics, NoUpdateOnTimeStretch) { 68 TickTimer timer; 69 StatisticsCalculator stats(&timer); 70 stats.DecodedOutputPlayed(); 71 stats.ExpandedVoiceSamples(100, false); 72 stats.AcceleratedSamples(4711); 73 stats.PreemptiveExpandedSamples(17); 74 stats.ExpandedVoiceSamples(100, false); 75 EXPECT_EQ(200u, stats.GetLifetimeStatistics().concealed_samples); 76 } 77 78 TEST(StatisticsCalculator, ExpandedSamplesCorrection) { 79 TickTimer timer; 80 StatisticsCalculator stats(&timer); 81 stats.DecodedOutputPlayed(); 82 NetEqNetworkStatistics stats_output; 83 constexpr int kSampleRateHz = 48000; 84 constexpr int k10MsSamples = kSampleRateHz / 100; 85 constexpr int kPacketSizeMs = 20; 86 constexpr size_t kSamplesPerPacket = kPacketSizeMs * kSampleRateHz / 1000; 87 88 // Advance time by 10 ms. 89 stats.IncreaseCounter(k10MsSamples, kSampleRateHz); 90 91 stats.GetNetworkStatistics(kSamplesPerPacket, &stats_output); 92 93 EXPECT_EQ(0u, stats_output.expand_rate); 94 EXPECT_EQ(0u, stats_output.speech_expand_rate); 95 96 // Correct with a negative value. 97 stats.ExpandedVoiceSamplesCorrection(-100); 98 stats.ExpandedNoiseSamplesCorrection(-100); 99 stats.IncreaseCounter(k10MsSamples, kSampleRateHz); 100 stats.GetNetworkStatistics(kSamplesPerPacket, &stats_output); 101 // Expect no change, since negative values are disallowed. 102 EXPECT_EQ(0u, stats_output.expand_rate); 103 EXPECT_EQ(0u, stats_output.speech_expand_rate); 104 105 // Correct with a positive value. 106 stats.ExpandedVoiceSamplesCorrection(50); 107 stats.ExpandedNoiseSamplesCorrection(200); 108 stats.IncreaseCounter(k10MsSamples, kSampleRateHz); 109 stats.GetNetworkStatistics(kSamplesPerPacket, &stats_output); 110 // Calculate expected rates in Q14. Expand rate is noise + voice, while 111 // speech expand rate is only voice. 112 EXPECT_EQ(((50u + 200u) << 14) / k10MsSamples, stats_output.expand_rate); 113 EXPECT_EQ((50u << 14) / k10MsSamples, stats_output.speech_expand_rate); 114 } 115 116 TEST(StatisticsCalculator, RelativePacketArrivalDelay) { 117 TickTimer timer; 118 StatisticsCalculator stats(&timer); 119 120 stats.RelativePacketArrivalDelay(50); 121 NetEqLifetimeStatistics stats_output = stats.GetLifetimeStatistics(); 122 EXPECT_EQ(50u, stats_output.relative_packet_arrival_delay_ms); 123 124 stats.RelativePacketArrivalDelay(20); 125 stats_output = stats.GetLifetimeStatistics(); 126 EXPECT_EQ(70u, stats_output.relative_packet_arrival_delay_ms); 127 } 128 129 TEST(StatisticsCalculator, ReceivedPacket) { 130 TickTimer timer; 131 StatisticsCalculator stats(&timer); 132 133 stats.ReceivedPacket(); 134 NetEqLifetimeStatistics stats_output = stats.GetLifetimeStatistics(); 135 EXPECT_EQ(1u, stats_output.jitter_buffer_packets_received); 136 137 stats.ReceivedPacket(); 138 stats_output = stats.GetLifetimeStatistics(); 139 EXPECT_EQ(2u, stats_output.jitter_buffer_packets_received); 140 } 141 142 TEST(StatisticsCalculator, InterruptionCounter) { 143 constexpr int fs_khz = 48; 144 constexpr int fs_hz = fs_khz * 1000; 145 TickTimer timer; 146 StatisticsCalculator stats(&timer); 147 stats.DecodedOutputPlayed(); 148 stats.EndExpandEvent(fs_hz); 149 auto lts = stats.GetLifetimeStatistics(); 150 EXPECT_EQ(0, lts.interruption_count); 151 EXPECT_EQ(0, lts.total_interruption_duration_ms); 152 153 // Add an event that is shorter than 150 ms. Should not be logged. 154 stats.ExpandedVoiceSamples(10 * fs_khz, false); // 10 ms. 155 stats.ExpandedNoiseSamples(139 * fs_khz, false); // 139 ms. 156 stats.EndExpandEvent(fs_hz); 157 lts = stats.GetLifetimeStatistics(); 158 EXPECT_EQ(0, lts.interruption_count); 159 160 // Add an event that is longer than 150 ms. Should be logged. 161 stats.ExpandedVoiceSamples(140 * fs_khz, false); // 140 ms. 162 stats.ExpandedNoiseSamples(11 * fs_khz, false); // 11 ms. 163 stats.EndExpandEvent(fs_hz); 164 lts = stats.GetLifetimeStatistics(); 165 EXPECT_EQ(1, lts.interruption_count); 166 EXPECT_EQ(151, lts.total_interruption_duration_ms); 167 168 // Add one more long event. 169 stats.ExpandedVoiceSamples(100 * fs_khz, false); // 100 ms. 170 stats.ExpandedNoiseSamples(5000 * fs_khz, false); // 5000 ms. 171 stats.EndExpandEvent(fs_hz); 172 lts = stats.GetLifetimeStatistics(); 173 EXPECT_EQ(2, lts.interruption_count); 174 EXPECT_EQ(5100 + 151, lts.total_interruption_duration_ms); 175 } 176 177 TEST(StatisticsCalculator, InterruptionCounterDoNotLogBeforeDecoding) { 178 constexpr int fs_khz = 48; 179 constexpr int fs_hz = fs_khz * 1000; 180 TickTimer timer; 181 StatisticsCalculator stats(&timer); 182 183 // Add an event that is longer than 150 ms. Should normally be logged, but we 184 // have not called DecodedOutputPlayed() yet, so it shouldn't this time. 185 stats.ExpandedVoiceSamples(151 * fs_khz, false); // 151 ms. 186 stats.EndExpandEvent(fs_hz); 187 auto lts = stats.GetLifetimeStatistics(); 188 EXPECT_EQ(0, lts.interruption_count); 189 190 // Call DecodedOutputPlayed(). Logging should happen after this. 191 stats.DecodedOutputPlayed(); 192 193 // Add one more long event. 194 stats.ExpandedVoiceSamples(151 * fs_khz, false); // 151 ms. 195 stats.EndExpandEvent(fs_hz); 196 lts = stats.GetLifetimeStatistics(); 197 EXPECT_EQ(1, lts.interruption_count); 198 } 199 200 TEST(StatisticsCalculator, DiscardedPackets) { 201 TickTimer timer; 202 StatisticsCalculator statistics_calculator(&timer); 203 EXPECT_EQ(0u, 204 statistics_calculator.GetLifetimeStatistics().packets_discarded); 205 206 statistics_calculator.PacketsDiscarded(1); 207 EXPECT_EQ(1u, 208 statistics_calculator.GetLifetimeStatistics().packets_discarded); 209 210 statistics_calculator.PacketsDiscarded(10); 211 EXPECT_EQ(11u, 212 statistics_calculator.GetLifetimeStatistics().packets_discarded); 213 214 // Calling `SecondaryPacketsDiscarded` does not modify `packets_discarded`. 215 statistics_calculator.SecondaryPacketsDiscarded(1); 216 EXPECT_EQ(11u, 217 statistics_calculator.GetLifetimeStatistics().packets_discarded); 218 219 // Calling `FlushedPacketBuffer` does not modify `packets_discarded`. 220 statistics_calculator.FlushedPacketBuffer(); 221 EXPECT_EQ(11u, 222 statistics_calculator.GetLifetimeStatistics().packets_discarded); 223 } 224 225 TEST(StatisticsCalculator, JitterBufferDelay) { 226 TickTimer timer; 227 StatisticsCalculator stats(&timer); 228 NetEqLifetimeStatistics lts; 229 lts = stats.GetLifetimeStatistics(); 230 EXPECT_EQ(lts.total_processing_delay_us, 0ul); 231 stats.JitterBufferDelay(/*num_samples=*/480, 232 /*waiting_time_ms=*/90ul, 233 /*target_delay_ms=*/80ul, 234 /*unlimited_target_delay_ms=*/70, 235 /*processing_delay_us=*/100 * 1000ul); 236 lts = stats.GetLifetimeStatistics(); 237 EXPECT_EQ(lts.jitter_buffer_delay_ms / 480, 90ul); 238 EXPECT_EQ(lts.jitter_buffer_target_delay_ms / 480, 80ul); 239 EXPECT_EQ(lts.jitter_buffer_minimum_delay_ms / 480, 70ul); 240 EXPECT_EQ(lts.total_processing_delay_us / 480, 100 * 1000ul); 241 EXPECT_EQ(lts.jitter_buffer_emitted_count, 480ul); 242 stats.JitterBufferDelay(/*num_samples=*/480, 243 /*waiting_time_ms=*/90ul, 244 /*target_delay_ms=*/80ul, 245 /*unlimited_target_delay_ms=*/70, 246 /*processing_delay_us=*/100 * 1000ul); 247 lts = stats.GetLifetimeStatistics(); 248 EXPECT_EQ(lts.jitter_buffer_delay_ms / 960, 90ul); 249 EXPECT_EQ(lts.jitter_buffer_target_delay_ms / 960, 80ul); 250 EXPECT_EQ(lts.jitter_buffer_minimum_delay_ms / 960, 70ul); 251 EXPECT_EQ(lts.total_processing_delay_us / 960, 100 * 1000ul); 252 EXPECT_EQ(lts.jitter_buffer_emitted_count, 960ul); 253 } 254 255 TEST(StatisticsCalculator, CountStatsAfterFirstDecodedPacket) { 256 TickTimer timer; 257 StatisticsCalculator stats(&timer); 258 stats.IncreaseCounter(/*num_samples=*/480, /*fs_hz=*/48000); 259 stats.ExpandedVoiceSamples(/*num_samples=*/480, 260 /*is_new_concealment_event=*/true); 261 NetEqLifetimeStatistics lts = stats.GetLifetimeStatistics(); 262 EXPECT_EQ(lts.total_samples_received, 0u); 263 EXPECT_EQ(lts.concealed_samples, 0u); 264 stats.DecodedOutputPlayed(); 265 stats.IncreaseCounter(/*num_samples=*/480, /*fs_hz=*/48000); 266 lts = stats.GetLifetimeStatistics(); 267 EXPECT_EQ(lts.total_samples_received, 480u); 268 } 269 270 } // namespace webrtc