OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include <algorithm> | 11 #include <algorithm> |
12 #include <limits> | 12 #include <limits> |
13 #include <list> | 13 #include <list> |
14 #include <memory> | 14 #include <memory> |
15 #include <numeric> | 15 #include <numeric> |
16 #include <string> | 16 #include <string> |
17 #include <vector> | 17 #include <vector> |
18 | 18 |
19 #include "webrtc/base/arraysize.h" | 19 #include "webrtc/base/arraysize.h" |
20 #include "webrtc/base/criticalsection.h" | 20 #include "webrtc/base/criticalsection.h" |
21 #include "webrtc/base/format_macros.h" | 21 #include "webrtc/base/format_macros.h" |
22 #include "webrtc/base/scoped_ref_ptr.h" | 22 #include "webrtc/base/scoped_ref_ptr.h" |
23 #include "webrtc/base/timeutils.h" | |
23 #include "webrtc/modules/audio_device/android/audio_common.h" | 24 #include "webrtc/modules/audio_device/android/audio_common.h" |
24 #include "webrtc/modules/audio_device/android/audio_manager.h" | 25 #include "webrtc/modules/audio_device/android/audio_manager.h" |
25 #include "webrtc/modules/audio_device/android/build_info.h" | 26 #include "webrtc/modules/audio_device/android/build_info.h" |
26 #include "webrtc/modules/audio_device/android/ensure_initialized.h" | 27 #include "webrtc/modules/audio_device/android/ensure_initialized.h" |
27 #include "webrtc/modules/audio_device/audio_device_impl.h" | 28 #include "webrtc/modules/audio_device/audio_device_impl.h" |
28 #include "webrtc/modules/audio_device/include/audio_device.h" | 29 #include "webrtc/modules/audio_device/include/audio_device.h" |
29 #include "webrtc/modules/audio_device/include/mock_audio_transport.h" | 30 #include "webrtc/modules/audio_device/include/mock_audio_transport.h" |
30 #include "webrtc/system_wrappers/include/clock.h" | |
31 #include "webrtc/system_wrappers/include/event_wrapper.h" | 31 #include "webrtc/system_wrappers/include/event_wrapper.h" |
32 #include "webrtc/system_wrappers/include/sleep.h" | 32 #include "webrtc/system_wrappers/include/sleep.h" |
33 #include "webrtc/test/gmock.h" | 33 #include "webrtc/test/gmock.h" |
34 #include "webrtc/test/gtest.h" | 34 #include "webrtc/test/gtest.h" |
35 #include "webrtc/test/testsupport/fileutils.h" | 35 #include "webrtc/test/testsupport/fileutils.h" |
36 | 36 |
37 using std::cout; | 37 using std::cout; |
38 using std::endl; | 38 using std::endl; |
39 using ::testing::_; | 39 using ::testing::_; |
40 using ::testing::AtLeast; | 40 using ::testing::AtLeast; |
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
245 size_t write_count_; | 245 size_t write_count_; |
246 }; | 246 }; |
247 | 247 |
248 // Inserts periodic impulses and measures the latency between the time of | 248 // Inserts periodic impulses and measures the latency between the time of |
249 // transmission and time of receiving the same impulse. | 249 // transmission and time of receiving the same impulse. |
250 // Usage requires a special hardware called Audio Loopback Dongle. | 250 // Usage requires a special hardware called Audio Loopback Dongle. |
251 // See http://source.android.com/devices/audio/loopback.html for details. | 251 // See http://source.android.com/devices/audio/loopback.html for details. |
252 class LatencyMeasuringAudioStream : public AudioStreamInterface { | 252 class LatencyMeasuringAudioStream : public AudioStreamInterface { |
253 public: | 253 public: |
254 explicit LatencyMeasuringAudioStream(size_t frames_per_buffer) | 254 explicit LatencyMeasuringAudioStream(size_t frames_per_buffer) |
255 : clock_(Clock::GetRealTimeClock()), | 255 : frames_per_buffer_(frames_per_buffer), |
256 frames_per_buffer_(frames_per_buffer), | |
257 bytes_per_buffer_(frames_per_buffer_ * sizeof(int16_t)), | 256 bytes_per_buffer_(frames_per_buffer_ * sizeof(int16_t)), |
258 play_count_(0), | 257 play_count_(0), |
259 rec_count_(0), | 258 rec_count_(0), |
260 pulse_time_(0) { | 259 pulse_time_(0) { |
261 } | 260 } |
262 | 261 |
263 // Insert periodic impulses in first two samples of |destination|. | 262 // Insert periodic impulses in first two samples of |destination|. |
264 void Read(void* destination, size_t num_frames) override { | 263 void Read(void* destination, size_t num_frames) override { |
265 ASSERT_EQ(num_frames, frames_per_buffer_); | 264 ASSERT_EQ(num_frames, frames_per_buffer_); |
266 if (play_count_ == 0) { | 265 if (play_count_ == 0) { |
267 PRINT("["); | 266 PRINT("["); |
268 } | 267 } |
269 play_count_++; | 268 play_count_++; |
270 memset(destination, 0, bytes_per_buffer_); | 269 memset(destination, 0, bytes_per_buffer_); |
271 if (play_count_ % (kNumCallbacksPerSecond / kImpulseFrequencyInHz) == 0) { | 270 if (play_count_ % (kNumCallbacksPerSecond / kImpulseFrequencyInHz) == 0) { |
272 if (pulse_time_ == 0) { | 271 if (pulse_time_ == 0) { |
273 pulse_time_ = clock_->TimeInMilliseconds(); | 272 pulse_time_ = rtc::TimeMillis(); |
274 } | 273 } |
275 PRINT("."); | 274 PRINT("."); |
276 const int16_t impulse = std::numeric_limits<int16_t>::max(); | 275 const int16_t impulse = std::numeric_limits<int16_t>::max(); |
277 int16_t* ptr16 = static_cast<int16_t*> (destination); | 276 int16_t* ptr16 = static_cast<int16_t*> (destination); |
278 for (size_t i = 0; i < 2; ++i) { | 277 for (size_t i = 0; i < 2; ++i) { |
279 ptr16[i] = impulse; | 278 ptr16[i] = impulse; |
280 } | 279 } |
281 } | 280 } |
282 } | 281 } |
283 | 282 |
(...skipping 10 matching lines...) Expand all Loading... | |
294 const int16_t* ptr16 = static_cast<const int16_t*> (source); | 293 const int16_t* ptr16 = static_cast<const int16_t*> (source); |
295 std::vector<int16_t> vec(ptr16, ptr16 + num_frames); | 294 std::vector<int16_t> vec(ptr16, ptr16 + num_frames); |
296 // Find max value in the audio buffer. | 295 // Find max value in the audio buffer. |
297 int max = *std::max_element(vec.begin(), vec.end()); | 296 int max = *std::max_element(vec.begin(), vec.end()); |
298 // Find index (element position in vector) of the max element. | 297 // Find index (element position in vector) of the max element. |
299 int index_of_max = std::distance(vec.begin(), | 298 int index_of_max = std::distance(vec.begin(), |
300 std::find(vec.begin(), vec.end(), | 299 std::find(vec.begin(), vec.end(), |
301 max)); | 300 max)); |
302 if (max > kImpulseThreshold) { | 301 if (max > kImpulseThreshold) { |
303 PRINTD("(%d,%d)", max, index_of_max); | 302 PRINTD("(%d,%d)", max, index_of_max); |
304 int64_t now_time = clock_->TimeInMilliseconds(); | 303 int64_t now_time = rtc::TimeMillis(); |
305 int extra_delay = IndexToMilliseconds(static_cast<double> (index_of_max)); | 304 int extra_delay = IndexToMilliseconds(static_cast<double> (index_of_max)); |
306 PRINTD("[%d]", static_cast<int> (now_time - pulse_time_)); | 305 PRINTD("[%d]", static_cast<int> (now_time - pulse_time_)); |
307 PRINTD("[%d]", extra_delay); | 306 PRINTD("[%d]", extra_delay); |
308 // Total latency is the difference between transmit time and detection | 307 // Total latency is the difference between transmit time and detection |
309 // tome plus the extra delay within the buffer in which we detected the | 308 // tome plus the extra delay within the buffer in which we detected the |
310 // received impulse. It is transmitted at sample 0 but can be received | 309 // received impulse. It is transmitted at sample 0 but can be received |
311 // at sample N where N > 0. The term |extra_delay| accounts for N and it | 310 // at sample N where N > 0. The term |extra_delay| accounts for N and it |
312 // is a value between 0 and 10ms. | 311 // is a value between 0 and 10ms. |
313 latencies_.push_back(now_time - pulse_time_ + extra_delay); | 312 latencies_.push_back(now_time - pulse_time_ + extra_delay); |
314 pulse_time_ = 0; | 313 pulse_time_ = 0; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
349 PRINT("\n"); | 348 PRINT("\n"); |
350 PRINT("%s[min, max, avg]=[%d, %d, %d] ms\n", kTag, | 349 PRINT("%s[min, max, avg]=[%d, %d, %d] ms\n", kTag, |
351 min_latency(), max_latency(), average_latency()); | 350 min_latency(), max_latency(), average_latency()); |
352 } | 351 } |
353 | 352 |
354 int IndexToMilliseconds(double index) const { | 353 int IndexToMilliseconds(double index) const { |
355 return static_cast<int>(10.0 * (index / frames_per_buffer_) + 0.5); | 354 return static_cast<int>(10.0 * (index / frames_per_buffer_) + 0.5); |
356 } | 355 } |
357 | 356 |
358 private: | 357 private: |
359 Clock* clock_; | |
360 const size_t frames_per_buffer_; | 358 const size_t frames_per_buffer_; |
361 const size_t bytes_per_buffer_; | 359 const size_t bytes_per_buffer_; |
362 size_t play_count_; | 360 size_t play_count_; |
363 size_t rec_count_; | 361 size_t rec_count_; |
364 int64_t pulse_time_; | 362 int64_t pulse_time_; |
365 std::vector<int> latencies_; | 363 std::vector<int> latencies_; |
366 }; | 364 }; |
367 | 365 |
368 // Mocks the AudioTransport object and proxies actions for the two callbacks | 366 // Mocks the AudioTransport object and proxies actions for the two callbacks |
369 // (RecordedDataIsAvailable and NeedMorePlayData) to different implementations | 367 // (RecordedDataIsAvailable and NeedMorePlayData) to different implementations |
(...skipping 622 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
992 | 990 |
993 // Measures loopback latency and reports the min, max and average values for | 991 // Measures loopback latency and reports the min, max and average values for |
994 // a full duplex audio session. | 992 // a full duplex audio session. |
995 // The latency is measured like so: | 993 // The latency is measured like so: |
996 // - Insert impulses periodically on the output side. | 994 // - Insert impulses periodically on the output side. |
997 // - Detect the impulses on the input side. | 995 // - Detect the impulses on the input side. |
998 // - Measure the time difference between the transmit time and receive time. | 996 // - Measure the time difference between the transmit time and receive time. |
999 // - Store time differences in a vector and calculate min, max and average. | 997 // - Store time differences in a vector and calculate min, max and average. |
1000 // This test requires a special hardware called Audio Loopback Dongle. | 998 // This test requires a special hardware called Audio Loopback Dongle. |
1001 // See http://source.android.com/devices/audio/loopback.html for details. | 999 // See http://source.android.com/devices/audio/loopback.html for details. |
1002 TEST_F(AudioDeviceTest, DISABLED_MeasureLoopbackLatency) { | 1000 TEST_F(AudioDeviceTest, MeasureLoopbackLatency) { |
nisse-webrtc
2016/11/15 08:12:33
Nice it the test can now be enabled, but it's uncl
| |
1003 EXPECT_EQ(record_channels(), playout_channels()); | 1001 EXPECT_EQ(record_channels(), playout_channels()); |
1004 EXPECT_EQ(record_sample_rate(), playout_sample_rate()); | 1002 EXPECT_EQ(record_sample_rate(), playout_sample_rate()); |
1005 NiceMock<MockAudioTransportAndroid> mock(kPlayout | kRecording); | 1003 NiceMock<MockAudioTransportAndroid> mock(kPlayout | kRecording); |
1006 std::unique_ptr<LatencyMeasuringAudioStream> latency_audio_stream( | 1004 std::unique_ptr<LatencyMeasuringAudioStream> latency_audio_stream( |
1007 new LatencyMeasuringAudioStream(playout_frames_per_10ms_buffer())); | 1005 new LatencyMeasuringAudioStream(playout_frames_per_10ms_buffer())); |
1008 mock.HandleCallbacks(test_is_done_.get(), | 1006 mock.HandleCallbacks(test_is_done_.get(), |
1009 latency_audio_stream.get(), | 1007 latency_audio_stream.get(), |
1010 kMeasureLatencyTimeInSec * kNumCallbacksPerSecond); | 1008 kMeasureLatencyTimeInSec * kNumCallbacksPerSecond); |
1011 EXPECT_EQ(0, audio_device()->RegisterAudioCallback(&mock)); | 1009 EXPECT_EQ(0, audio_device()->RegisterAudioCallback(&mock)); |
1012 SetMaxPlayoutVolume(); | 1010 SetMaxPlayoutVolume(); |
1013 DisableBuiltInAECIfAvailable(); | 1011 DisableBuiltInAECIfAvailable(); |
1014 StartRecording(); | 1012 StartRecording(); |
1015 StartPlayout(); | 1013 StartPlayout(); |
1016 test_is_done_->Wait(std::max(kTestTimeOutInMilliseconds, | 1014 test_is_done_->Wait(std::max(kTestTimeOutInMilliseconds, |
1017 1000 * kMeasureLatencyTimeInSec)); | 1015 1000 * kMeasureLatencyTimeInSec)); |
1018 StopPlayout(); | 1016 StopPlayout(); |
1019 StopRecording(); | 1017 StopRecording(); |
1020 // Verify that the correct number of transmitted impulses are detected. | 1018 // Verify that the correct number of transmitted impulses are detected. |
1021 EXPECT_EQ(latency_audio_stream->num_latency_values(), | 1019 EXPECT_EQ(latency_audio_stream->num_latency_values(), |
1022 static_cast<size_t>( | 1020 static_cast<size_t>( |
1023 kImpulseFrequencyInHz * kMeasureLatencyTimeInSec - 1)); | 1021 kImpulseFrequencyInHz * kMeasureLatencyTimeInSec - 1)); |
1024 latency_audio_stream->PrintResults(); | 1022 latency_audio_stream->PrintResults(); |
1025 } | 1023 } |
1026 | 1024 |
1027 } // namespace webrtc | 1025 } // namespace webrtc |
OLD | NEW |