peah | 5585001 | 2016-03-19 18:01:09 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 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 | #include <vector> |
| 11 | |
Mirko Bonadei | 92ea95e | 2017-09-15 06:47:31 +0200 | [diff] [blame] | 12 | #include "api/array_view.h" |
| 13 | #include "modules/audio_processing/audio_buffer.h" |
Per Åhgren | 0cbb58e | 2019-10-29 22:59:44 +0100 | [diff] [blame] | 14 | #include "modules/audio_processing/legacy_noise_suppression.h" |
Mirko Bonadei | 92ea95e | 2017-09-15 06:47:31 +0200 | [diff] [blame] | 15 | #include "modules/audio_processing/test/audio_buffer_tools.h" |
| 16 | #include "modules/audio_processing/test/bitexactness_tools.h" |
| 17 | #include "test/gtest.h" |
peah | 5585001 | 2016-03-19 18:01:09 -0700 | [diff] [blame] | 18 | |
| 19 | namespace webrtc { |
| 20 | namespace { |
| 21 | |
| 22 | const int kNumFramesToProcess = 1000; |
| 23 | |
| 24 | // Process one frame of data and produce the output. |
| 25 | void ProcessOneFrame(int sample_rate_hz, |
| 26 | AudioBuffer* capture_buffer, |
saza | 0bad15f | 2019-10-16 11:46:11 +0200 | [diff] [blame] | 27 | NoiseSuppression* noise_suppressor) { |
peah | 5585001 | 2016-03-19 18:01:09 -0700 | [diff] [blame] | 28 | if (sample_rate_hz > AudioProcessing::kSampleRate16kHz) { |
| 29 | capture_buffer->SplitIntoFrequencyBands(); |
| 30 | } |
| 31 | |
| 32 | noise_suppressor->AnalyzeCaptureAudio(capture_buffer); |
| 33 | noise_suppressor->ProcessCaptureAudio(capture_buffer); |
| 34 | |
| 35 | if (sample_rate_hz > AudioProcessing::kSampleRate16kHz) { |
| 36 | capture_buffer->MergeFrequencyBands(); |
| 37 | } |
| 38 | } |
| 39 | |
| 40 | // Processes a specified amount of frames, verifies the results and reports |
| 41 | // any errors. |
| 42 | void RunBitexactnessTest(int sample_rate_hz, |
| 43 | size_t num_channels, |
saza | 0bad15f | 2019-10-16 11:46:11 +0200 | [diff] [blame] | 44 | NoiseSuppression::Level level, |
peah | 5585001 | 2016-03-19 18:01:09 -0700 | [diff] [blame] | 45 | float speech_probability_reference, |
| 46 | rtc::ArrayView<const float> noise_estimate_reference, |
| 47 | rtc::ArrayView<const float> output_reference) { |
saza | 0bad15f | 2019-10-16 11:46:11 +0200 | [diff] [blame] | 48 | NoiseSuppression noise_suppressor(num_channels, sample_rate_hz, level); |
peah | 5585001 | 2016-03-19 18:01:09 -0700 | [diff] [blame] | 49 | |
| 50 | int samples_per_channel = rtc::CheckedDivExact(sample_rate_hz, 100); |
| 51 | const StreamConfig capture_config(sample_rate_hz, num_channels, false); |
| 52 | AudioBuffer capture_buffer( |
Per Åhgren | d47941e | 2019-08-22 11:51:13 +0200 | [diff] [blame] | 53 | capture_config.sample_rate_hz(), capture_config.num_channels(), |
| 54 | capture_config.sample_rate_hz(), capture_config.num_channels(), |
| 55 | capture_config.sample_rate_hz(), capture_config.num_channels()); |
peah | 5585001 | 2016-03-19 18:01:09 -0700 | [diff] [blame] | 56 | test::InputAudioFile capture_file( |
| 57 | test::GetApmCaptureTestVectorFileName(sample_rate_hz)); |
| 58 | std::vector<float> capture_input(samples_per_channel * num_channels); |
| 59 | for (size_t frame_no = 0; frame_no < kNumFramesToProcess; ++frame_no) { |
| 60 | ReadFloatSamplesFromStereoFile(samples_per_channel, num_channels, |
| 61 | &capture_file, capture_input); |
| 62 | |
| 63 | test::CopyVectorToAudioBuffer(capture_config, capture_input, |
| 64 | &capture_buffer); |
| 65 | |
| 66 | ProcessOneFrame(sample_rate_hz, &capture_buffer, &noise_suppressor); |
| 67 | } |
| 68 | |
| 69 | // Extract test results. |
| 70 | std::vector<float> capture_output; |
| 71 | test::ExtractVectorFromAudioBuffer(capture_config, &capture_buffer, |
| 72 | &capture_output); |
| 73 | float speech_probability = noise_suppressor.speech_probability(); |
| 74 | std::vector<float> noise_estimate = noise_suppressor.NoiseEstimate(); |
| 75 | |
peah | 7ea928e | 2016-03-30 08:13:57 -0700 | [diff] [blame] | 76 | const float kVectorElementErrorBound = 1.0f / 32768.0f; |
peah | 5585001 | 2016-03-19 18:01:09 -0700 | [diff] [blame] | 77 | EXPECT_FLOAT_EQ(speech_probability_reference, speech_probability); |
peah | 7ea928e | 2016-03-30 08:13:57 -0700 | [diff] [blame] | 78 | EXPECT_TRUE(test::VerifyArray(noise_estimate_reference, noise_estimate, |
| 79 | kVectorElementErrorBound)); |
peah | 5585001 | 2016-03-19 18:01:09 -0700 | [diff] [blame] | 80 | |
| 81 | // Compare the output with the reference. Only the first values of the output |
| 82 | // from last frame processed are compared in order not having to specify all |
| 83 | // preceeding frames as testvectors. As the algorithm being tested has a |
| 84 | // memory, testing only the last frame implicitly also tests the preceeding |
| 85 | // frames. |
peah | 7ea928e | 2016-03-30 08:13:57 -0700 | [diff] [blame] | 86 | EXPECT_TRUE(test::VerifyDeinterleavedArray( |
peah | 5585001 | 2016-03-19 18:01:09 -0700 | [diff] [blame] | 87 | capture_config.num_frames(), capture_config.num_channels(), |
peah | 7ea928e | 2016-03-30 08:13:57 -0700 | [diff] [blame] | 88 | output_reference, capture_output, kVectorElementErrorBound)); |
peah | 5585001 | 2016-03-19 18:01:09 -0700 | [diff] [blame] | 89 | } |
| 90 | |
| 91 | } // namespace |
| 92 | |
Per Åhgren | 0cbb58e | 2019-10-29 22:59:44 +0100 | [diff] [blame] | 93 | TEST(LegacyNoiseSuppresionBitExactnessTest, Mono8kHzLow) { |
peah | 5585001 | 2016-03-19 18:01:09 -0700 | [diff] [blame] | 94 | #if defined(WEBRTC_ARCH_ARM64) |
| 95 | const float kSpeechProbabilityReference = -4.0f; |
Yves Gerey | 665174f | 2018-06-19 15:03:05 +0200 | [diff] [blame] | 96 | const float kNoiseEstimateReference[] = {1432.341431f, 3321.919922f, |
| 97 | 7677.521973f}; |
peah | 5585001 | 2016-03-19 18:01:09 -0700 | [diff] [blame] | 98 | const float kOutputReference[] = {0.003510f, 0.004517f, 0.004669f}; |
| 99 | #elif defined(WEBRTC_ARCH_ARM) |
| 100 | const float kSpeechProbabilityReference = -4.0f; |
Yves Gerey | 665174f | 2018-06-19 15:03:05 +0200 | [diff] [blame] | 101 | const float kNoiseEstimateReference[] = {1432.341431f, 3321.919922f, |
| 102 | 7677.521973f}; |
peah | 5585001 | 2016-03-19 18:01:09 -0700 | [diff] [blame] | 103 | const float kOutputReference[] = {0.003510f, 0.004517f, 0.004669f}; |
| 104 | #else |
Per Åhgren | 62c174c | 2019-08-16 13:43:00 +0200 | [diff] [blame] | 105 | const float kSpeechProbabilityReference = 0.73650402f; |
| 106 | const float kNoiseEstimateReference[] = {1176.856812f, 3287.490967f, |
| 107 | 7525.964844f}; |
| 108 | const float kOutputReference[] = {0.003306f, 0.004442f, 0.004574f}; |
peah | 5585001 | 2016-03-19 18:01:09 -0700 | [diff] [blame] | 109 | #endif |
| 110 | |
| 111 | RunBitexactnessTest(8000, 1, NoiseSuppression::Level::kLow, |
| 112 | kSpeechProbabilityReference, kNoiseEstimateReference, |
| 113 | kOutputReference); |
| 114 | } |
| 115 | |
Per Åhgren | 0cbb58e | 2019-10-29 22:59:44 +0100 | [diff] [blame] | 116 | TEST(LegacyNoiseSuppresionBitExactnessTest, Mono16kHzLow) { |
peah | 5585001 | 2016-03-19 18:01:09 -0700 | [diff] [blame] | 117 | #if defined(WEBRTC_ARCH_ARM64) |
| 118 | const float kSpeechProbabilityReference = -4.0f; |
Yves Gerey | 665174f | 2018-06-19 15:03:05 +0200 | [diff] [blame] | 119 | const float kNoiseEstimateReference[] = {2534.461914f, 6277.638672f, |
| 120 | 14367.499023f}; |
peah | 5585001 | 2016-03-19 18:01:09 -0700 | [diff] [blame] | 121 | const float kOutputReference[] = {0.003449f, 0.004334f, 0.004303f}; |
| 122 | #elif defined(WEBRTC_ARCH_ARM) |
| 123 | const float kSpeechProbabilityReference = -4.0f; |
Yves Gerey | 665174f | 2018-06-19 15:03:05 +0200 | [diff] [blame] | 124 | const float kNoiseEstimateReference[] = {2534.461914f, 6277.638672f, |
| 125 | 14367.499023f}; |
peah | 5585001 | 2016-03-19 18:01:09 -0700 | [diff] [blame] | 126 | const float kOutputReference[] = {0.003449f, 0.004334f, 0.004303f}; |
| 127 | #else |
Per Åhgren | 62c174c | 2019-08-16 13:43:00 +0200 | [diff] [blame] | 128 | const float kSpeechProbabilityReference = 0.71743423f; |
| 129 | const float kNoiseEstimateReference[] = {2179.853027f, 6507.995117f, |
| 130 | 15652.758789f}; |
peah | 5585001 | 2016-03-19 18:01:09 -0700 | [diff] [blame] | 131 | const float kOutputReference[] = {0.003574f, 0.004494f, 0.004499f}; |
| 132 | #endif |
| 133 | |
| 134 | RunBitexactnessTest(16000, 1, NoiseSuppression::Level::kLow, |
| 135 | kSpeechProbabilityReference, kNoiseEstimateReference, |
| 136 | kOutputReference); |
| 137 | } |
| 138 | |
Per Åhgren | 0cbb58e | 2019-10-29 22:59:44 +0100 | [diff] [blame] | 139 | TEST(LegacyNoiseSuppresionBitExactnessTest, Mono32kHzLow) { |
peah | 5585001 | 2016-03-19 18:01:09 -0700 | [diff] [blame] | 140 | #if defined(WEBRTC_ARCH_ARM64) |
| 141 | const float kSpeechProbabilityReference = -4.0f; |
Yves Gerey | 665174f | 2018-06-19 15:03:05 +0200 | [diff] [blame] | 142 | const float kNoiseEstimateReference[] = {2540.059082f, 6317.822754f, |
| 143 | 14440.845703f}; |
peah | 5585001 | 2016-03-19 18:01:09 -0700 | [diff] [blame] | 144 | const float kOutputReference[] = {0.001679f, 0.002411f, 0.002594f}; |
| 145 | #elif defined(WEBRTC_ARCH_ARM) |
| 146 | const float kSpeechProbabilityReference = -4.0f; |
Yves Gerey | 665174f | 2018-06-19 15:03:05 +0200 | [diff] [blame] | 147 | const float kNoiseEstimateReference[] = {2540.059082f, 6317.822754f, |
| 148 | 14440.845703f}; |
peah | 5585001 | 2016-03-19 18:01:09 -0700 | [diff] [blame] | 149 | const float kOutputReference[] = {0.001679f, 0.002411f, 0.002594f}; |
| 150 | #else |
| 151 | const float kSpeechProbabilityReference = 0.67999554f; |
Yves Gerey | 665174f | 2018-06-19 15:03:05 +0200 | [diff] [blame] | 152 | const float kNoiseEstimateReference[] = {2149.780518f, 7076.936035f, |
| 153 | 14939.945312f}; |
peah | 5585001 | 2016-03-19 18:01:09 -0700 | [diff] [blame] | 154 | const float kOutputReference[] = {0.001221f, 0.001984f, 0.002228f}; |
| 155 | #endif |
| 156 | |
| 157 | RunBitexactnessTest(32000, 1, NoiseSuppression::Level::kLow, |
| 158 | kSpeechProbabilityReference, kNoiseEstimateReference, |
| 159 | kOutputReference); |
| 160 | } |
| 161 | |
Per Åhgren | 0cbb58e | 2019-10-29 22:59:44 +0100 | [diff] [blame] | 162 | TEST(LegacyNoiseSuppresionBitExactnessTest, Mono48kHzLow) { |
peah | 5585001 | 2016-03-19 18:01:09 -0700 | [diff] [blame] | 163 | #if defined(WEBRTC_ARCH_ARM64) |
| 164 | const float kSpeechProbabilityReference = -4.0f; |
Per Åhgren | 62c174c | 2019-08-16 13:43:00 +0200 | [diff] [blame] | 165 | const float kNoiseEstimateReference[] = {2135.292480f, 6692.695801f, |
| 166 | 14647.632812f}; |
| 167 | const float kOutputReference[] = {-0.012738f, -0.012312f, -0.011576f}; |
peah | 5585001 | 2016-03-19 18:01:09 -0700 | [diff] [blame] | 168 | #elif defined(WEBRTC_ARCH_ARM) |
| 169 | const float kSpeechProbabilityReference = -4.0f; |
Per Åhgren | 62c174c | 2019-08-16 13:43:00 +0200 | [diff] [blame] | 170 | const float kNoiseEstimateReference[] = {2135.292480f, 6692.695801f, |
| 171 | 14647.632812f}; |
| 172 | const float kOutputReference[] = {-0.012738f, -0.012312f, -0.011576f}; |
peah | 5585001 | 2016-03-19 18:01:09 -0700 | [diff] [blame] | 173 | #else |
Per Åhgren | 62c174c | 2019-08-16 13:43:00 +0200 | [diff] [blame] | 174 | const float kSpeechProbabilityReference = 0.70737761f; |
| 175 | const float kNoiseEstimateReference[] = {2187.394043f, 6913.306641f, |
| 176 | 13182.945312f}; |
peah | 5585001 | 2016-03-19 18:01:09 -0700 | [diff] [blame] | 177 | const float kOutputReference[] = {-0.013062f, -0.012657f, -0.011934f}; |
| 178 | #endif |
| 179 | |
| 180 | RunBitexactnessTest(48000, 1, NoiseSuppression::Level::kLow, |
| 181 | kSpeechProbabilityReference, kNoiseEstimateReference, |
| 182 | kOutputReference); |
| 183 | } |
| 184 | |
Per Åhgren | 0cbb58e | 2019-10-29 22:59:44 +0100 | [diff] [blame] | 185 | TEST(LegacyNoiseSuppresionBitExactnessTest, Stereo16kHzLow) { |
peah | 5585001 | 2016-03-19 18:01:09 -0700 | [diff] [blame] | 186 | #if defined(WEBRTC_ARCH_ARM64) |
| 187 | const float kSpeechProbabilityReference = -4.0f; |
Yves Gerey | 665174f | 2018-06-19 15:03:05 +0200 | [diff] [blame] | 188 | const float kNoiseEstimateReference[] = {9992.127930f, 12689.569336f, |
| 189 | 11589.296875f}; |
peah | 5585001 | 2016-03-19 18:01:09 -0700 | [diff] [blame] | 190 | const float kOutputReference[] = {-0.011108f, -0.007904f, -0.012390f, |
| 191 | -0.002441f, 0.000855f, -0.003204f}; |
| 192 | #elif defined(WEBRTC_ARCH_ARM) |
| 193 | const float kSpeechProbabilityReference = -4.0f; |
Yves Gerey | 665174f | 2018-06-19 15:03:05 +0200 | [diff] [blame] | 194 | const float kNoiseEstimateReference[] = {10321.353516f, 12133.852539f, |
| 195 | 10923.060547f}; |
peah | 5585001 | 2016-03-19 18:01:09 -0700 | [diff] [blame] | 196 | const float kOutputReference[] = {-0.011108f, -0.007904f, -0.012390f, |
| 197 | -0.002472f, 0.000916f, -0.003235f}; |
| 198 | #else |
Per Åhgren | 62c174c | 2019-08-16 13:43:00 +0200 | [diff] [blame] | 199 | const float kSpeechProbabilityReference = 0.67285913f; |
| 200 | const float kNoiseEstimateReference[] = {9753.257812f, 11515.603516f, |
| 201 | 10503.309570f}; |
peah | 5585001 | 2016-03-19 18:01:09 -0700 | [diff] [blame] | 202 | const float kOutputReference[] = {-0.011459f, -0.008110f, -0.012728f, |
| 203 | -0.002399f, 0.001018f, -0.003189f}; |
| 204 | #endif |
| 205 | |
| 206 | RunBitexactnessTest(16000, 2, NoiseSuppression::Level::kLow, |
| 207 | kSpeechProbabilityReference, kNoiseEstimateReference, |
| 208 | kOutputReference); |
| 209 | } |
| 210 | |
Per Åhgren | 0cbb58e | 2019-10-29 22:59:44 +0100 | [diff] [blame] | 211 | TEST(LegacyNoiseSuppresionBitExactnessTest, Mono16kHzModerate) { |
peah | 5585001 | 2016-03-19 18:01:09 -0700 | [diff] [blame] | 212 | #if defined(WEBRTC_ARCH_ARM64) |
| 213 | const float kSpeechProbabilityReference = -4.0f; |
Yves Gerey | 665174f | 2018-06-19 15:03:05 +0200 | [diff] [blame] | 214 | const float kNoiseEstimateReference[] = {2057.085938f, 7601.055176f, |
| 215 | 19666.187500f}; |
peah | 5585001 | 2016-03-19 18:01:09 -0700 | [diff] [blame] | 216 | const float kOutputReference[] = {0.004669f, 0.005524f, 0.005432f}; |
| 217 | #elif defined(WEBRTC_ARCH_ARM) |
| 218 | const float kSpeechProbabilityReference = -4.0f; |
Yves Gerey | 665174f | 2018-06-19 15:03:05 +0200 | [diff] [blame] | 219 | const float kNoiseEstimateReference[] = {2244.497803f, 6864.164062f, |
| 220 | 16726.523438f}; |
peah | 5585001 | 2016-03-19 18:01:09 -0700 | [diff] [blame] | 221 | const float kOutputReference[] = {0.004669f, 0.005615f, 0.005585f}; |
| 222 | #else |
Per Åhgren | 62c174c | 2019-08-16 13:43:00 +0200 | [diff] [blame] | 223 | const float kSpeechProbabilityReference = 0.70916927f; |
| 224 | const float kNoiseEstimateReference[] = {2172.830566f, 6552.661133f, |
| 225 | 15624.025391f}; |
peah | 5585001 | 2016-03-19 18:01:09 -0700 | [diff] [blame] | 226 | const float kOutputReference[] = {0.004513f, 0.005590f, 0.005614f}; |
| 227 | #endif |
| 228 | |
| 229 | RunBitexactnessTest(16000, 1, NoiseSuppression::Level::kModerate, |
| 230 | kSpeechProbabilityReference, kNoiseEstimateReference, |
| 231 | kOutputReference); |
| 232 | } |
| 233 | |
Per Åhgren | 0cbb58e | 2019-10-29 22:59:44 +0100 | [diff] [blame] | 234 | TEST(LegacyNoiseSuppresionBitExactnessTest, Mono16kHzHigh) { |
peah | 5585001 | 2016-03-19 18:01:09 -0700 | [diff] [blame] | 235 | #if defined(WEBRTC_ARCH_ARM64) |
| 236 | const float kSpeechProbabilityReference = -4.0f; |
Yves Gerey | 665174f | 2018-06-19 15:03:05 +0200 | [diff] [blame] | 237 | const float kNoiseEstimateReference[] = {2095.148193f, 7698.553711f, |
| 238 | 19689.533203f}; |
peah | 5585001 | 2016-03-19 18:01:09 -0700 | [diff] [blame] | 239 | const float kOutputReference[] = {0.004639f, 0.005402f, 0.005310f}; |
| 240 | #elif defined(WEBRTC_ARCH_ARM) |
| 241 | const float kSpeechProbabilityReference = -4.0f; |
Yves Gerey | 665174f | 2018-06-19 15:03:05 +0200 | [diff] [blame] | 242 | const float kNoiseEstimateReference[] = {2282.515625f, 6984.408203f, |
| 243 | 16920.960938f}; |
peah | 5585001 | 2016-03-19 18:01:09 -0700 | [diff] [blame] | 244 | const float kOutputReference[] = {0.004547f, 0.005432f, 0.005402f}; |
| 245 | #else |
Per Åhgren | 62c174c | 2019-08-16 13:43:00 +0200 | [diff] [blame] | 246 | const float kSpeechProbabilityReference = 0.70104003f; |
| 247 | const float kNoiseEstimateReference[] = {2225.081055f, 6711.529785f, |
| 248 | 15785.949219}; |
peah | 5585001 | 2016-03-19 18:01:09 -0700 | [diff] [blame] | 249 | const float kOutputReference[] = {0.004394f, 0.005406f, 0.005416f}; |
| 250 | #endif |
| 251 | |
| 252 | RunBitexactnessTest(16000, 1, NoiseSuppression::Level::kHigh, |
| 253 | kSpeechProbabilityReference, kNoiseEstimateReference, |
| 254 | kOutputReference); |
| 255 | } |
| 256 | |
Per Åhgren | 0cbb58e | 2019-10-29 22:59:44 +0100 | [diff] [blame] | 257 | TEST(LegacyNoiseSuppresionBitExactnessTest, Mono16kHzVeryHigh) { |
peah | 5585001 | 2016-03-19 18:01:09 -0700 | [diff] [blame] | 258 | #if defined(WEBRTC_ARCH_ARM64) |
| 259 | const float kSpeechProbabilityReference = -4.0f; |
Yves Gerey | 665174f | 2018-06-19 15:03:05 +0200 | [diff] [blame] | 260 | const float kNoiseEstimateReference[] = {2677.733398f, 6186.987305f, |
| 261 | 14365.744141f}; |
peah | 5585001 | 2016-03-19 18:01:09 -0700 | [diff] [blame] | 262 | const float kOutputReference[] = {0.004273f, 0.005127f, 0.005188f}; |
| 263 | #elif defined(WEBRTC_ARCH_ARM) |
| 264 | const float kSpeechProbabilityReference = -4.0f; |
Yves Gerey | 665174f | 2018-06-19 15:03:05 +0200 | [diff] [blame] | 265 | const float kNoiseEstimateReference[] = {2677.733398f, 6186.987305f, |
| 266 | 14365.744141f}; |
peah | 5585001 | 2016-03-19 18:01:09 -0700 | [diff] [blame] | 267 | const float kOutputReference[] = {0.004273f, 0.005127f, 0.005188f}; |
| 268 | #else |
Per Åhgren | 62c174c | 2019-08-16 13:43:00 +0200 | [diff] [blame] | 269 | const float kSpeechProbabilityReference = 0.70290041f; |
| 270 | const float kNoiseEstimateReference[] = {2254.921875f, 6723.172852f, |
| 271 | 15770.559570f}; |
peah | 5585001 | 2016-03-19 18:01:09 -0700 | [diff] [blame] | 272 | const float kOutputReference[] = {0.004321f, 0.005247f, 0.005263f}; |
| 273 | #endif |
| 274 | |
| 275 | RunBitexactnessTest(16000, 1, NoiseSuppression::Level::kVeryHigh, |
| 276 | kSpeechProbabilityReference, kNoiseEstimateReference, |
| 277 | kOutputReference); |
| 278 | } |
peah | 5585001 | 2016-03-19 18:01:09 -0700 | [diff] [blame] | 279 | } // namespace webrtc |