| 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 <numeric> | 15 #include <numeric> |
| 15 #include <string> | 16 #include <string> |
| 16 #include <vector> | 17 #include <vector> |
| 17 | 18 |
| 18 #include "testing/gmock/include/gmock/gmock.h" | 19 #include "testing/gmock/include/gmock/gmock.h" |
| 19 #include "testing/gtest/include/gtest/gtest.h" | 20 #include "testing/gtest/include/gtest/gtest.h" |
| 20 #include "webrtc/base/arraysize.h" | 21 #include "webrtc/base/arraysize.h" |
| 21 #include "webrtc/base/criticalsection.h" | 22 #include "webrtc/base/criticalsection.h" |
| 22 #include "webrtc/base/format_macros.h" | 23 #include "webrtc/base/format_macros.h" |
| 23 #include "webrtc/base/scoped_ptr.h" | |
| 24 #include "webrtc/base/scoped_ref_ptr.h" | 24 #include "webrtc/base/scoped_ref_ptr.h" |
| 25 #include "webrtc/modules/audio_device/android/audio_common.h" | 25 #include "webrtc/modules/audio_device/android/audio_common.h" |
| 26 #include "webrtc/modules/audio_device/android/audio_manager.h" | 26 #include "webrtc/modules/audio_device/android/audio_manager.h" |
| 27 #include "webrtc/modules/audio_device/android/build_info.h" | 27 #include "webrtc/modules/audio_device/android/build_info.h" |
| 28 #include "webrtc/modules/audio_device/android/ensure_initialized.h" | 28 #include "webrtc/modules/audio_device/android/ensure_initialized.h" |
| 29 #include "webrtc/modules/audio_device/audio_device_impl.h" | 29 #include "webrtc/modules/audio_device/audio_device_impl.h" |
| 30 #include "webrtc/modules/audio_device/include/audio_device.h" | 30 #include "webrtc/modules/audio_device/include/audio_device.h" |
| 31 #include "webrtc/system_wrappers/include/clock.h" | 31 #include "webrtc/system_wrappers/include/clock.h" |
| 32 #include "webrtc/system_wrappers/include/event_wrapper.h" | 32 #include "webrtc/system_wrappers/include/event_wrapper.h" |
| 33 #include "webrtc/system_wrappers/include/sleep.h" | 33 #include "webrtc/system_wrappers/include/sleep.h" |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 137 return static_cast<int>( | 137 return static_cast<int>( |
| 138 file_size_in_bytes_ / (kBytesPerSample * sample_rate_)); | 138 file_size_in_bytes_ / (kBytesPerSample * sample_rate_)); |
| 139 } | 139 } |
| 140 size_t file_size_in_callbacks() const { | 140 size_t file_size_in_callbacks() const { |
| 141 return file_size_in_seconds() * kNumCallbacksPerSecond; | 141 return file_size_in_seconds() * kNumCallbacksPerSecond; |
| 142 } | 142 } |
| 143 | 143 |
| 144 private: | 144 private: |
| 145 size_t file_size_in_bytes_; | 145 size_t file_size_in_bytes_; |
| 146 int sample_rate_; | 146 int sample_rate_; |
| 147 rtc::scoped_ptr<int16_t[]> file_; | 147 std::unique_ptr<int16_t[]> file_; |
| 148 size_t file_pos_; | 148 size_t file_pos_; |
| 149 }; | 149 }; |
| 150 | 150 |
| 151 // Simple first in first out (FIFO) class that wraps a list of 16-bit audio | 151 // Simple first in first out (FIFO) class that wraps a list of 16-bit audio |
| 152 // buffers of fixed size and allows Write and Read operations. The idea is to | 152 // buffers of fixed size and allows Write and Read operations. The idea is to |
| 153 // store recorded audio buffers (using Write) and then read (using Read) these | 153 // store recorded audio buffers (using Write) and then read (using Read) these |
| 154 // stored buffers with as short delay as possible when the audio layer needs | 154 // stored buffers with as short delay as possible when the audio layer needs |
| 155 // data to play out. The number of buffers in the FIFO will stabilize under | 155 // data to play out. The number of buffers in the FIFO will stabilize under |
| 156 // normal conditions since there will be a balance between Write and Read calls. | 156 // normal conditions since there will be a balance between Write and Read calls. |
| 157 // The container is a std::list container and access is protected with a lock | 157 // The container is a std::list container and access is protected with a lock |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 232 for (auto it = fifo_->begin(); it != fifo_->end(); ++it) { | 232 for (auto it = fifo_->begin(); it != fifo_->end(); ++it) { |
| 233 delete *it; | 233 delete *it; |
| 234 } | 234 } |
| 235 fifo_->clear(); | 235 fifo_->clear(); |
| 236 } | 236 } |
| 237 | 237 |
| 238 using AudioBufferList = std::list<int16_t*>; | 238 using AudioBufferList = std::list<int16_t*>; |
| 239 rtc::CriticalSection lock_; | 239 rtc::CriticalSection lock_; |
| 240 const size_t frames_per_buffer_; | 240 const size_t frames_per_buffer_; |
| 241 const size_t bytes_per_buffer_; | 241 const size_t bytes_per_buffer_; |
| 242 rtc::scoped_ptr<AudioBufferList> fifo_; | 242 std::unique_ptr<AudioBufferList> fifo_; |
| 243 size_t largest_size_; | 243 size_t largest_size_; |
| 244 size_t total_written_elements_; | 244 size_t total_written_elements_; |
| 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 { |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 484 bool play_mode() const { return type_ & kPlayout; } | 484 bool play_mode() const { return type_ & kPlayout; } |
| 485 bool rec_mode() const { return type_ & kRecording; } | 485 bool rec_mode() const { return type_ & kRecording; } |
| 486 | 486 |
| 487 private: | 487 private: |
| 488 EventWrapper* test_is_done_; | 488 EventWrapper* test_is_done_; |
| 489 size_t num_callbacks_; | 489 size_t num_callbacks_; |
| 490 int type_; | 490 int type_; |
| 491 size_t play_count_; | 491 size_t play_count_; |
| 492 size_t rec_count_; | 492 size_t rec_count_; |
| 493 AudioStreamInterface* audio_stream_; | 493 AudioStreamInterface* audio_stream_; |
| 494 rtc::scoped_ptr<LatencyMeasuringAudioStream> latency_audio_stream_; | 494 std::unique_ptr<LatencyMeasuringAudioStream> latency_audio_stream_; |
| 495 }; | 495 }; |
| 496 | 496 |
| 497 // AudioDeviceTest test fixture. | 497 // AudioDeviceTest test fixture. |
| 498 class AudioDeviceTest : public ::testing::Test { | 498 class AudioDeviceTest : public ::testing::Test { |
| 499 protected: | 499 protected: |
| 500 AudioDeviceTest() | 500 AudioDeviceTest() |
| 501 : test_is_done_(EventWrapper::Create()) { | 501 : test_is_done_(EventWrapper::Create()) { |
| 502 // One-time initialization of JVM and application context. Ensures that we | 502 // One-time initialization of JVM and application context. Ensures that we |
| 503 // can do calls between C++ and Java. Initializes both Java and OpenSL ES | 503 // can do calls between C++ and Java. Initializes both Java and OpenSL ES |
| 504 // implementations. | 504 // implementations. |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 681 EXPECT_EQ(0, audio_device()->MinSpeakerVolume(&min_volume)); | 681 EXPECT_EQ(0, audio_device()->MinSpeakerVolume(&min_volume)); |
| 682 return min_volume; | 682 return min_volume; |
| 683 } | 683 } |
| 684 | 684 |
| 685 int GetSpeakerVolume() const { | 685 int GetSpeakerVolume() const { |
| 686 uint32_t volume(0); | 686 uint32_t volume(0); |
| 687 EXPECT_EQ(0, audio_device()->SpeakerVolume(&volume)); | 687 EXPECT_EQ(0, audio_device()->SpeakerVolume(&volume)); |
| 688 return volume; | 688 return volume; |
| 689 } | 689 } |
| 690 | 690 |
| 691 rtc::scoped_ptr<EventWrapper> test_is_done_; | 691 std::unique_ptr<EventWrapper> test_is_done_; |
| 692 rtc::scoped_refptr<AudioDeviceModule> audio_device_; | 692 rtc::scoped_refptr<AudioDeviceModule> audio_device_; |
| 693 AudioParameters playout_parameters_; | 693 AudioParameters playout_parameters_; |
| 694 AudioParameters record_parameters_; | 694 AudioParameters record_parameters_; |
| 695 rtc::scoped_ptr<BuildInfo> build_info_; | 695 std::unique_ptr<BuildInfo> build_info_; |
| 696 }; | 696 }; |
| 697 | 697 |
| 698 TEST_F(AudioDeviceTest, ConstructDestruct) { | 698 TEST_F(AudioDeviceTest, ConstructDestruct) { |
| 699 // Using the test fixture to create and destruct the audio device module. | 699 // Using the test fixture to create and destruct the audio device module. |
| 700 } | 700 } |
| 701 | 701 |
| 702 // We always ask for a default audio layer when the ADM is constructed. But the | 702 // We always ask for a default audio layer when the ADM is constructed. But the |
| 703 // ADM will then internally set the best suitable combination of audio layers, | 703 // ADM will then internally set the best suitable combination of audio layers, |
| 704 // for input and output based on if low-latency output audio in combination | 704 // for input and output based on if low-latency output audio in combination |
| 705 // with OpenSL ES is supported or not. This test ensures that the correct | 705 // with OpenSL ES is supported or not. This test ensures that the correct |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 928 | 928 |
| 929 // Start playout and read audio from an external PCM file when the audio layer | 929 // Start playout and read audio from an external PCM file when the audio layer |
| 930 // asks for data to play out. Real audio is played out in this test but it does | 930 // asks for data to play out. Real audio is played out in this test but it does |
| 931 // not contain any explicit verification that the audio quality is perfect. | 931 // not contain any explicit verification that the audio quality is perfect. |
| 932 TEST_F(AudioDeviceTest, RunPlayoutWithFileAsSource) { | 932 TEST_F(AudioDeviceTest, RunPlayoutWithFileAsSource) { |
| 933 // TODO(henrika): extend test when mono output is supported. | 933 // TODO(henrika): extend test when mono output is supported. |
| 934 EXPECT_EQ(1u, playout_channels()); | 934 EXPECT_EQ(1u, playout_channels()); |
| 935 NiceMock<MockAudioTransport> mock(kPlayout); | 935 NiceMock<MockAudioTransport> mock(kPlayout); |
| 936 const int num_callbacks = kFilePlayTimeInSec * kNumCallbacksPerSecond; | 936 const int num_callbacks = kFilePlayTimeInSec * kNumCallbacksPerSecond; |
| 937 std::string file_name = GetFileName(playout_sample_rate()); | 937 std::string file_name = GetFileName(playout_sample_rate()); |
| 938 rtc::scoped_ptr<FileAudioStream> file_audio_stream( | 938 std::unique_ptr<FileAudioStream> file_audio_stream( |
| 939 new FileAudioStream(num_callbacks, file_name, playout_sample_rate())); | 939 new FileAudioStream(num_callbacks, file_name, playout_sample_rate())); |
| 940 mock.HandleCallbacks(test_is_done_.get(), | 940 mock.HandleCallbacks(test_is_done_.get(), |
| 941 file_audio_stream.get(), | 941 file_audio_stream.get(), |
| 942 num_callbacks); | 942 num_callbacks); |
| 943 // SetMaxPlayoutVolume(); | 943 // SetMaxPlayoutVolume(); |
| 944 EXPECT_EQ(0, audio_device()->RegisterAudioCallback(&mock)); | 944 EXPECT_EQ(0, audio_device()->RegisterAudioCallback(&mock)); |
| 945 StartPlayout(); | 945 StartPlayout(); |
| 946 test_is_done_->Wait(kTestTimeOutInMilliseconds); | 946 test_is_done_->Wait(kTestTimeOutInMilliseconds); |
| 947 StopPlayout(); | 947 StopPlayout(); |
| 948 } | 948 } |
| 949 | 949 |
| 950 // Start playout and recording and store recorded data in an intermediate FIFO | 950 // Start playout and recording and store recorded data in an intermediate FIFO |
| 951 // buffer from which the playout side then reads its samples in the same order | 951 // buffer from which the playout side then reads its samples in the same order |
| 952 // as they were stored. Under ideal circumstances, a callback sequence would | 952 // as they were stored. Under ideal circumstances, a callback sequence would |
| 953 // look like: ...+-+-+-+-+-+-+-..., where '+' means 'packet recorded' and '-' | 953 // look like: ...+-+-+-+-+-+-+-..., where '+' means 'packet recorded' and '-' |
| 954 // means 'packet played'. Under such conditions, the FIFO would only contain | 954 // means 'packet played'. Under such conditions, the FIFO would only contain |
| 955 // one packet on average. However, under more realistic conditions, the size | 955 // one packet on average. However, under more realistic conditions, the size |
| 956 // of the FIFO will vary more due to an unbalance between the two sides. | 956 // of the FIFO will vary more due to an unbalance between the two sides. |
| 957 // This test tries to verify that the device maintains a balanced callback- | 957 // This test tries to verify that the device maintains a balanced callback- |
| 958 // sequence by running in loopback for ten seconds while measuring the size | 958 // sequence by running in loopback for ten seconds while measuring the size |
| 959 // (max and average) of the FIFO. The size of the FIFO is increased by the | 959 // (max and average) of the FIFO. The size of the FIFO is increased by the |
| 960 // recording side and decreased by the playout side. | 960 // recording side and decreased by the playout side. |
| 961 // TODO(henrika): tune the final test parameters after running tests on several | 961 // TODO(henrika): tune the final test parameters after running tests on several |
| 962 // different devices. | 962 // different devices. |
| 963 TEST_F(AudioDeviceTest, RunPlayoutAndRecordingInFullDuplex) { | 963 TEST_F(AudioDeviceTest, RunPlayoutAndRecordingInFullDuplex) { |
| 964 EXPECT_EQ(record_channels(), playout_channels()); | 964 EXPECT_EQ(record_channels(), playout_channels()); |
| 965 EXPECT_EQ(record_sample_rate(), playout_sample_rate()); | 965 EXPECT_EQ(record_sample_rate(), playout_sample_rate()); |
| 966 NiceMock<MockAudioTransport> mock(kPlayout | kRecording); | 966 NiceMock<MockAudioTransport> mock(kPlayout | kRecording); |
| 967 rtc::scoped_ptr<FifoAudioStream> fifo_audio_stream( | 967 std::unique_ptr<FifoAudioStream> fifo_audio_stream( |
| 968 new FifoAudioStream(playout_frames_per_10ms_buffer())); | 968 new FifoAudioStream(playout_frames_per_10ms_buffer())); |
| 969 mock.HandleCallbacks(test_is_done_.get(), | 969 mock.HandleCallbacks(test_is_done_.get(), |
| 970 fifo_audio_stream.get(), | 970 fifo_audio_stream.get(), |
| 971 kFullDuplexTimeInSec * kNumCallbacksPerSecond); | 971 kFullDuplexTimeInSec * kNumCallbacksPerSecond); |
| 972 SetMaxPlayoutVolume(); | 972 SetMaxPlayoutVolume(); |
| 973 EXPECT_EQ(0, audio_device()->RegisterAudioCallback(&mock)); | 973 EXPECT_EQ(0, audio_device()->RegisterAudioCallback(&mock)); |
| 974 StartRecording(); | 974 StartRecording(); |
| 975 StartPlayout(); | 975 StartPlayout(); |
| 976 test_is_done_->Wait(std::max(kTestTimeOutInMilliseconds, | 976 test_is_done_->Wait(std::max(kTestTimeOutInMilliseconds, |
| 977 1000 * kFullDuplexTimeInSec)); | 977 1000 * kFullDuplexTimeInSec)); |
| 978 StopPlayout(); | 978 StopPlayout(); |
| 979 StopRecording(); | 979 StopRecording(); |
| 980 EXPECT_LE(fifo_audio_stream->average_size(), 10u); | 980 EXPECT_LE(fifo_audio_stream->average_size(), 10u); |
| 981 EXPECT_LE(fifo_audio_stream->largest_size(), 20u); | 981 EXPECT_LE(fifo_audio_stream->largest_size(), 20u); |
| 982 } | 982 } |
| 983 | 983 |
| 984 // Measures loopback latency and reports the min, max and average values for | 984 // Measures loopback latency and reports the min, max and average values for |
| 985 // a full duplex audio session. | 985 // a full duplex audio session. |
| 986 // The latency is measured like so: | 986 // The latency is measured like so: |
| 987 // - Insert impulses periodically on the output side. | 987 // - Insert impulses periodically on the output side. |
| 988 // - Detect the impulses on the input side. | 988 // - Detect the impulses on the input side. |
| 989 // - Measure the time difference between the transmit time and receive time. | 989 // - Measure the time difference between the transmit time and receive time. |
| 990 // - Store time differences in a vector and calculate min, max and average. | 990 // - Store time differences in a vector and calculate min, max and average. |
| 991 // This test requires a special hardware called Audio Loopback Dongle. | 991 // This test requires a special hardware called Audio Loopback Dongle. |
| 992 // See http://source.android.com/devices/audio/loopback.html for details. | 992 // See http://source.android.com/devices/audio/loopback.html for details. |
| 993 TEST_F(AudioDeviceTest, DISABLED_MeasureLoopbackLatency) { | 993 TEST_F(AudioDeviceTest, DISABLED_MeasureLoopbackLatency) { |
| 994 EXPECT_EQ(record_channels(), playout_channels()); | 994 EXPECT_EQ(record_channels(), playout_channels()); |
| 995 EXPECT_EQ(record_sample_rate(), playout_sample_rate()); | 995 EXPECT_EQ(record_sample_rate(), playout_sample_rate()); |
| 996 NiceMock<MockAudioTransport> mock(kPlayout | kRecording); | 996 NiceMock<MockAudioTransport> mock(kPlayout | kRecording); |
| 997 rtc::scoped_ptr<LatencyMeasuringAudioStream> latency_audio_stream( | 997 std::unique_ptr<LatencyMeasuringAudioStream> latency_audio_stream( |
| 998 new LatencyMeasuringAudioStream(playout_frames_per_10ms_buffer())); | 998 new LatencyMeasuringAudioStream(playout_frames_per_10ms_buffer())); |
| 999 mock.HandleCallbacks(test_is_done_.get(), | 999 mock.HandleCallbacks(test_is_done_.get(), |
| 1000 latency_audio_stream.get(), | 1000 latency_audio_stream.get(), |
| 1001 kMeasureLatencyTimeInSec * kNumCallbacksPerSecond); | 1001 kMeasureLatencyTimeInSec * kNumCallbacksPerSecond); |
| 1002 EXPECT_EQ(0, audio_device()->RegisterAudioCallback(&mock)); | 1002 EXPECT_EQ(0, audio_device()->RegisterAudioCallback(&mock)); |
| 1003 SetMaxPlayoutVolume(); | 1003 SetMaxPlayoutVolume(); |
| 1004 DisableBuiltInAECIfAvailable(); | 1004 DisableBuiltInAECIfAvailable(); |
| 1005 StartRecording(); | 1005 StartRecording(); |
| 1006 StartPlayout(); | 1006 StartPlayout(); |
| 1007 test_is_done_->Wait(std::max(kTestTimeOutInMilliseconds, | 1007 test_is_done_->Wait(std::max(kTestTimeOutInMilliseconds, |
| 1008 1000 * kMeasureLatencyTimeInSec)); | 1008 1000 * kMeasureLatencyTimeInSec)); |
| 1009 StopPlayout(); | 1009 StopPlayout(); |
| 1010 StopRecording(); | 1010 StopRecording(); |
| 1011 // Verify that the correct number of transmitted impulses are detected. | 1011 // Verify that the correct number of transmitted impulses are detected. |
| 1012 EXPECT_EQ(latency_audio_stream->num_latency_values(), | 1012 EXPECT_EQ(latency_audio_stream->num_latency_values(), |
| 1013 static_cast<size_t>( | 1013 static_cast<size_t>( |
| 1014 kImpulseFrequencyInHz * kMeasureLatencyTimeInSec - 1)); | 1014 kImpulseFrequencyInHz * kMeasureLatencyTimeInSec - 1)); |
| 1015 latency_audio_stream->PrintResults(); | 1015 latency_audio_stream->PrintResults(); |
| 1016 } | 1016 } |
| 1017 | 1017 |
| 1018 } // namespace webrtc | 1018 } // namespace webrtc |
| OLD | NEW |