| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 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 <assert.h> | 11 #include <assert.h> |
| 12 | 12 |
| 13 #include "webrtc/modules/audio_device/audio_device_config.h" | 13 #include "webrtc/modules/audio_device/audio_device_config.h" |
| 14 #include "webrtc/modules/audio_device/linux/audio_device_alsa_linux.h" | 14 #include "webrtc/modules/audio_device/linux/audio_device_alsa_linux.h" |
| 15 #include "webrtc/rtc_base/logging.h" | 15 #include "webrtc/rtc_base/logging.h" |
| 16 | 16 |
| 17 #include "webrtc/system_wrappers/include/event_wrapper.h" | 17 #include "webrtc/system_wrappers/include/event_wrapper.h" |
| 18 #include "webrtc/system_wrappers/include/sleep.h" | 18 #include "webrtc/system_wrappers/include/sleep.h" |
| 19 #include "webrtc/system_wrappers/include/trace.h" | |
| 20 | |
| 21 webrtc::adm_linux_alsa::AlsaSymbolTable AlsaSymbolTable; | 19 webrtc::adm_linux_alsa::AlsaSymbolTable AlsaSymbolTable; |
| 22 | 20 |
| 23 // Accesses ALSA functions through our late-binding symbol table instead of | 21 // Accesses ALSA functions through our late-binding symbol table instead of |
| 24 // directly. This way we don't have to link to libasound, which means our binary | 22 // directly. This way we don't have to link to libasound, which means our binary |
| 25 // will work on systems that don't have it. | 23 // will work on systems that don't have it. |
| 26 #define LATE(sym) \ | 24 #define LATE(sym) \ |
| 27 LATESYM_GET(webrtc::adm_linux_alsa::AlsaSymbolTable, &AlsaSymbolTable, sym) | 25 LATESYM_GET(webrtc::adm_linux_alsa::AlsaSymbolTable, &AlsaSymbolTable, sym) |
| 28 | 26 |
| 29 // Redefine these here to be able to do late-binding | 27 // Redefine these here to be able to do late-binding |
| 30 #undef snd_ctl_card_info_alloca | 28 #undef snd_ctl_card_info_alloca |
| (...skipping 24 matching lines...) Expand all Loading... |
| 55 static const unsigned int ALSA_CAPTURE_CH = 2; | 53 static const unsigned int ALSA_CAPTURE_CH = 2; |
| 56 static const unsigned int ALSA_CAPTURE_LATENCY = 40*1000; // in us | 54 static const unsigned int ALSA_CAPTURE_LATENCY = 40*1000; // in us |
| 57 static const unsigned int ALSA_CAPTURE_WAIT_TIMEOUT = 5; // in ms | 55 static const unsigned int ALSA_CAPTURE_WAIT_TIMEOUT = 5; // in ms |
| 58 | 56 |
| 59 #define FUNC_GET_NUM_OF_DEVICE 0 | 57 #define FUNC_GET_NUM_OF_DEVICE 0 |
| 60 #define FUNC_GET_DEVICE_NAME 1 | 58 #define FUNC_GET_DEVICE_NAME 1 |
| 61 #define FUNC_GET_DEVICE_NAME_FOR_AN_ENUM 2 | 59 #define FUNC_GET_DEVICE_NAME_FOR_AN_ENUM 2 |
| 62 | 60 |
| 63 AudioDeviceLinuxALSA::AudioDeviceLinuxALSA(const int32_t id) : | 61 AudioDeviceLinuxALSA::AudioDeviceLinuxALSA(const int32_t id) : |
| 64 _ptrAudioBuffer(NULL), | 62 _ptrAudioBuffer(NULL), |
| 65 _id(id), | |
| 66 _mixerManager(id), | 63 _mixerManager(id), |
| 67 _inputDeviceIndex(0), | 64 _inputDeviceIndex(0), |
| 68 _outputDeviceIndex(0), | 65 _outputDeviceIndex(0), |
| 69 _inputDeviceIsSpecified(false), | 66 _inputDeviceIsSpecified(false), |
| 70 _outputDeviceIsSpecified(false), | 67 _outputDeviceIsSpecified(false), |
| 71 _handleRecord(NULL), | 68 _handleRecord(NULL), |
| 72 _handlePlayout(NULL), | 69 _handlePlayout(NULL), |
| 73 _recordingBuffersizeInFrame(0), | 70 _recordingBuffersizeInFrame(0), |
| 74 _recordingPeriodSizeInFrame(0), | 71 _recordingPeriodSizeInFrame(0), |
| 75 _playoutBufferSizeInFrame(0), | 72 _playoutBufferSizeInFrame(0), |
| (...skipping 20 matching lines...) Expand all Loading... |
| 96 _recordingDelay(0), | 93 _recordingDelay(0), |
| 97 _playoutDelay(0), | 94 _playoutDelay(0), |
| 98 _playWarning(0), | 95 _playWarning(0), |
| 99 _playError(0), | 96 _playError(0), |
| 100 _recWarning(0), | 97 _recWarning(0), |
| 101 _recError(0), | 98 _recError(0), |
| 102 _playBufDelay(80), | 99 _playBufDelay(80), |
| 103 _playBufDelayFixed(80) | 100 _playBufDelayFixed(80) |
| 104 { | 101 { |
| 105 memset(_oldKeyState, 0, sizeof(_oldKeyState)); | 102 memset(_oldKeyState, 0, sizeof(_oldKeyState)); |
| 106 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, id, | 103 LOG(LS_INFO) << __FUNCTION__ << " created"; |
| 107 "%s created", __FUNCTION__); | |
| 108 } | 104 } |
| 109 | 105 |
| 110 // ---------------------------------------------------------------------------- | 106 // ---------------------------------------------------------------------------- |
| 111 // AudioDeviceLinuxALSA - dtor | 107 // AudioDeviceLinuxALSA - dtor |
| 112 // ---------------------------------------------------------------------------- | 108 // ---------------------------------------------------------------------------- |
| 113 | 109 |
| 114 AudioDeviceLinuxALSA::~AudioDeviceLinuxALSA() | 110 AudioDeviceLinuxALSA::~AudioDeviceLinuxALSA() |
| 115 { | 111 { |
| 116 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, | 112 LOG(LS_INFO) << __FUNCTION__ << " destroyed"; |
| 117 "%s destroyed", __FUNCTION__); | |
| 118 | 113 |
| 119 Terminate(); | 114 Terminate(); |
| 120 | 115 |
| 121 // Clean up the recording buffer and playout buffer. | 116 // Clean up the recording buffer and playout buffer. |
| 122 if (_recordingBuffer) | 117 if (_recordingBuffer) |
| 123 { | 118 { |
| 124 delete [] _recordingBuffer; | 119 delete [] _recordingBuffer; |
| 125 _recordingBuffer = NULL; | 120 _recordingBuffer = NULL; |
| 126 } | 121 } |
| 127 if (_playoutBuffer) | 122 if (_playoutBuffer) |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 325 volume = level; | 320 volume = level; |
| 326 | 321 |
| 327 return 0; | 322 return 0; |
| 328 } | 323 } |
| 329 | 324 |
| 330 | 325 |
| 331 int32_t AudioDeviceLinuxALSA::SetWaveOutVolume(uint16_t volumeLeft, | 326 int32_t AudioDeviceLinuxALSA::SetWaveOutVolume(uint16_t volumeLeft, |
| 332 uint16_t volumeRight) | 327 uint16_t volumeRight) |
| 333 { | 328 { |
| 334 | 329 |
| 335 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, | 330 LOG(LS_WARNING) << "API call not supported on this platform"; |
| 336 " API call not supported on this platform"); | |
| 337 return -1; | 331 return -1; |
| 338 } | 332 } |
| 339 | 333 |
| 340 int32_t AudioDeviceLinuxALSA::WaveOutVolume( | 334 int32_t AudioDeviceLinuxALSA::WaveOutVolume( |
| 341 uint16_t& /*volumeLeft*/, | 335 uint16_t& /*volumeLeft*/, |
| 342 uint16_t& /*volumeRight*/) const | 336 uint16_t& /*volumeRight*/) const |
| 343 { | 337 { |
| 344 | 338 |
| 345 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, | 339 LOG(LS_WARNING) << "API call not supported on this platform"; |
| 346 " API call not supported on this platform"); | |
| 347 return -1; | 340 return -1; |
| 348 } | 341 } |
| 349 | 342 |
| 350 int32_t AudioDeviceLinuxALSA::MaxSpeakerVolume( | 343 int32_t AudioDeviceLinuxALSA::MaxSpeakerVolume( |
| 351 uint32_t& maxVolume) const | 344 uint32_t& maxVolume) const |
| 352 { | 345 { |
| 353 | 346 |
| 354 uint32_t maxVol(0); | 347 uint32_t maxVol(0); |
| 355 | 348 |
| 356 if (_mixerManager.MaxSpeakerVolume(maxVol) == -1) | 349 if (_mixerManager.MaxSpeakerVolume(maxVol) == -1) |
| (...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 747 return 0; | 740 return 0; |
| 748 } | 741 } |
| 749 | 742 |
| 750 int32_t AudioDeviceLinuxALSA::MicrophoneVolume(uint32_t& volume) const | 743 int32_t AudioDeviceLinuxALSA::MicrophoneVolume(uint32_t& volume) const |
| 751 { | 744 { |
| 752 | 745 |
| 753 uint32_t level(0); | 746 uint32_t level(0); |
| 754 | 747 |
| 755 if (_mixerManager.MicrophoneVolume(level) == -1) | 748 if (_mixerManager.MicrophoneVolume(level) == -1) |
| 756 { | 749 { |
| 757 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, | 750 LOG(LS_WARNING) << "failed to retrive current microphone level"; |
| 758 " failed to retrive current microphone level"); | |
| 759 return -1; | 751 return -1; |
| 760 } | 752 } |
| 761 | 753 |
| 762 volume = level; | 754 volume = level; |
| 763 | 755 |
| 764 return 0; | 756 return 0; |
| 765 } | 757 } |
| 766 | 758 |
| 767 int32_t AudioDeviceLinuxALSA::MaxMicrophoneVolume( | 759 int32_t AudioDeviceLinuxALSA::MaxMicrophoneVolume( |
| 768 uint32_t& maxVolume) const | 760 uint32_t& maxVolume) const |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 820 | 812 |
| 821 int32_t AudioDeviceLinuxALSA::SetPlayoutDevice(uint16_t index) | 813 int32_t AudioDeviceLinuxALSA::SetPlayoutDevice(uint16_t index) |
| 822 { | 814 { |
| 823 | 815 |
| 824 if (_playIsInitialized) | 816 if (_playIsInitialized) |
| 825 { | 817 { |
| 826 return -1; | 818 return -1; |
| 827 } | 819 } |
| 828 | 820 |
| 829 uint32_t nDevices = GetDevicesInfo(0, true); | 821 uint32_t nDevices = GetDevicesInfo(0, true); |
| 830 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, | 822 LOG(LS_VERBOSE) << "number of available audio output devices is " |
| 831 " number of availiable audio output devices is %u", nDevices); | 823 << nDevices; |
| 832 | 824 |
| 833 if (index > (nDevices-1)) | 825 if (index > (nDevices-1)) |
| 834 { | 826 { |
| 835 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, | 827 LOG(LS_ERROR) << "device index is out of range [0," << (nDevices-1) |
| 836 " device index is out of range [0,%u]", (nDevices-1)); | 828 << "]"; |
| 837 return -1; | 829 return -1; |
| 838 } | 830 } |
| 839 | 831 |
| 840 _outputDeviceIndex = index; | 832 _outputDeviceIndex = index; |
| 841 _outputDeviceIsSpecified = true; | 833 _outputDeviceIsSpecified = true; |
| 842 | 834 |
| 843 return 0; | 835 return 0; |
| 844 } | 836 } |
| 845 | 837 |
| 846 int32_t AudioDeviceLinuxALSA::SetPlayoutDevice( | 838 int32_t AudioDeviceLinuxALSA::SetPlayoutDevice( |
| 847 AudioDeviceModule::WindowsDeviceType /*device*/) | 839 AudioDeviceModule::WindowsDeviceType /*device*/) |
| 848 { | 840 { |
| 849 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, | 841 LOG(LS_ERROR) << "WindowsDeviceType not supported"; |
| 850 "WindowsDeviceType not supported"); | |
| 851 return -1; | 842 return -1; |
| 852 } | 843 } |
| 853 | 844 |
| 854 int32_t AudioDeviceLinuxALSA::PlayoutDeviceName( | 845 int32_t AudioDeviceLinuxALSA::PlayoutDeviceName( |
| 855 uint16_t index, | 846 uint16_t index, |
| 856 char name[kAdmMaxDeviceNameSize], | 847 char name[kAdmMaxDeviceNameSize], |
| 857 char guid[kAdmMaxGuidSize]) | 848 char guid[kAdmMaxGuidSize]) |
| 858 { | 849 { |
| 859 | 850 |
| 860 const uint16_t nDevices(PlayoutDevices()); | 851 const uint16_t nDevices(PlayoutDevices()); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 905 | 896 |
| 906 int32_t AudioDeviceLinuxALSA::SetRecordingDevice(uint16_t index) | 897 int32_t AudioDeviceLinuxALSA::SetRecordingDevice(uint16_t index) |
| 907 { | 898 { |
| 908 | 899 |
| 909 if (_recIsInitialized) | 900 if (_recIsInitialized) |
| 910 { | 901 { |
| 911 return -1; | 902 return -1; |
| 912 } | 903 } |
| 913 | 904 |
| 914 uint32_t nDevices = GetDevicesInfo(0, false); | 905 uint32_t nDevices = GetDevicesInfo(0, false); |
| 915 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, | 906 LOG(LS_VERBOSE) << "number of availiable audio input devices is " |
| 916 " number of availiable audio input devices is %u", nDevices); | 907 << nDevices; |
| 917 | 908 |
| 918 if (index > (nDevices-1)) | 909 if (index > (nDevices-1)) |
| 919 { | 910 { |
| 920 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, | 911 LOG(LS_ERROR) << "device index is out of range [0," << (nDevices-1) |
| 921 " device index is out of range [0,%u]", (nDevices-1)); | 912 << "]"; |
| 922 return -1; | 913 return -1; |
| 923 } | 914 } |
| 924 | 915 |
| 925 _inputDeviceIndex = index; | 916 _inputDeviceIndex = index; |
| 926 _inputDeviceIsSpecified = true; | 917 _inputDeviceIsSpecified = true; |
| 927 | 918 |
| 928 return 0; | 919 return 0; |
| 929 } | 920 } |
| 930 | 921 |
| 931 // ---------------------------------------------------------------------------- | 922 // ---------------------------------------------------------------------------- |
| 932 // SetRecordingDevice II (II) | 923 // SetRecordingDevice II (II) |
| 933 // ---------------------------------------------------------------------------- | 924 // ---------------------------------------------------------------------------- |
| 934 | 925 |
| 935 int32_t AudioDeviceLinuxALSA::SetRecordingDevice( | 926 int32_t AudioDeviceLinuxALSA::SetRecordingDevice( |
| 936 AudioDeviceModule::WindowsDeviceType /*device*/) | 927 AudioDeviceModule::WindowsDeviceType /*device*/) |
| 937 { | 928 { |
| 938 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, | 929 LOG(LS_ERROR) << "WindowsDeviceType not supported"; |
| 939 "WindowsDeviceType not supported"); | |
| 940 return -1; | 930 return -1; |
| 941 } | 931 } |
| 942 | 932 |
| 943 int32_t AudioDeviceLinuxALSA::PlayoutIsAvailable(bool& available) | 933 int32_t AudioDeviceLinuxALSA::PlayoutIsAvailable(bool& available) |
| 944 { | 934 { |
| 945 | 935 |
| 946 available = false; | 936 available = false; |
| 947 | 937 |
| 948 // Try to initialize the playout side with mono | 938 // Try to initialize the playout side with mono |
| 949 // Assumes that user set num channels after calling this function | 939 // Assumes that user set num channels after calling this function |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1018 return -1; | 1008 return -1; |
| 1019 } | 1009 } |
| 1020 | 1010 |
| 1021 if (_playIsInitialized) | 1011 if (_playIsInitialized) |
| 1022 { | 1012 { |
| 1023 return 0; | 1013 return 0; |
| 1024 } | 1014 } |
| 1025 // Initialize the speaker (devices might have been added or removed) | 1015 // Initialize the speaker (devices might have been added or removed) |
| 1026 if (InitSpeaker() == -1) | 1016 if (InitSpeaker() == -1) |
| 1027 { | 1017 { |
| 1028 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, | 1018 LOG(LS_WARNING) << "InitSpeaker() failed"; |
| 1029 " InitSpeaker() failed"); | |
| 1030 } | 1019 } |
| 1031 | 1020 |
| 1032 // Start by closing any existing wave-output devices | 1021 // Start by closing any existing wave-output devices |
| 1033 // | 1022 // |
| 1034 if (_handlePlayout != NULL) | 1023 if (_handlePlayout != NULL) |
| 1035 { | 1024 { |
| 1036 LATE(snd_pcm_close)(_handlePlayout); | 1025 LATE(snd_pcm_close)(_handlePlayout); |
| 1037 _handlePlayout = NULL; | 1026 _handlePlayout = NULL; |
| 1038 _playIsInitialized = false; | 1027 _playIsInitialized = false; |
| 1039 if (errVal < 0) | 1028 if (errVal < 0) |
| 1040 { | 1029 { |
| 1041 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, | 1030 LOG(LS_ERROR) |
| 1042 " Error closing current playout sound device, error:" | 1031 << "Error closing current playout sound device, error: " |
| 1043 " %s", LATE(snd_strerror)(errVal)); | 1032 << LATE(snd_strerror)(errVal); |
| 1044 } | 1033 } |
| 1045 } | 1034 } |
| 1046 | 1035 |
| 1047 // Open PCM device for playout | 1036 // Open PCM device for playout |
| 1048 char deviceName[kAdmMaxDeviceNameSize] = {0}; | 1037 char deviceName[kAdmMaxDeviceNameSize] = {0}; |
| 1049 GetDevicesInfo(2, true, _outputDeviceIndex, deviceName, | 1038 GetDevicesInfo(2, true, _outputDeviceIndex, deviceName, |
| 1050 kAdmMaxDeviceNameSize); | 1039 kAdmMaxDeviceNameSize); |
| 1051 | 1040 |
| 1052 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, | 1041 LOG(LS_VERBOSE) << "InitPlayout open (" << deviceName << ")"; |
| 1053 " InitPlayout open (%s)", deviceName); | |
| 1054 | 1042 |
| 1055 errVal = LATE(snd_pcm_open) | 1043 errVal = LATE(snd_pcm_open) |
| 1056 (&_handlePlayout, | 1044 (&_handlePlayout, |
| 1057 deviceName, | 1045 deviceName, |
| 1058 SND_PCM_STREAM_PLAYBACK, | 1046 SND_PCM_STREAM_PLAYBACK, |
| 1059 SND_PCM_NONBLOCK); | 1047 SND_PCM_NONBLOCK); |
| 1060 | 1048 |
| 1061 if (errVal == -EBUSY) // Device busy - try some more! | 1049 if (errVal == -EBUSY) // Device busy - try some more! |
| 1062 { | 1050 { |
| 1063 for (int i=0; i < 5; i++) | 1051 for (int i=0; i < 5; i++) |
| 1064 { | 1052 { |
| 1065 SleepMs(1000); | 1053 SleepMs(1000); |
| 1066 errVal = LATE(snd_pcm_open) | 1054 errVal = LATE(snd_pcm_open) |
| 1067 (&_handlePlayout, | 1055 (&_handlePlayout, |
| 1068 deviceName, | 1056 deviceName, |
| 1069 SND_PCM_STREAM_PLAYBACK, | 1057 SND_PCM_STREAM_PLAYBACK, |
| 1070 SND_PCM_NONBLOCK); | 1058 SND_PCM_NONBLOCK); |
| 1071 if (errVal == 0) | 1059 if (errVal == 0) |
| 1072 { | 1060 { |
| 1073 break; | 1061 break; |
| 1074 } | 1062 } |
| 1075 } | 1063 } |
| 1076 } | 1064 } |
| 1077 if (errVal < 0) | 1065 if (errVal < 0) |
| 1078 { | 1066 { |
| 1079 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, | 1067 LOG(LS_ERROR) << "unable to open playback device: " |
| 1080 " unable to open playback device: %s (%d)", | 1068 << LATE(snd_strerror)(errVal) << " (" << errVal << ")"; |
| 1081 LATE(snd_strerror)(errVal), | |
| 1082 errVal); | |
| 1083 _handlePlayout = NULL; | 1069 _handlePlayout = NULL; |
| 1084 return -1; | 1070 return -1; |
| 1085 } | 1071 } |
| 1086 | 1072 |
| 1087 _playoutFramesIn10MS = _playoutFreq/100; | 1073 _playoutFramesIn10MS = _playoutFreq/100; |
| 1088 if ((errVal = LATE(snd_pcm_set_params)( _handlePlayout, | 1074 if ((errVal = LATE(snd_pcm_set_params)( _handlePlayout, |
| 1089 #if defined(WEBRTC_ARCH_BIG_ENDIAN) | 1075 #if defined(WEBRTC_ARCH_BIG_ENDIAN) |
| 1090 SND_PCM_FORMAT_S16_BE, | 1076 SND_PCM_FORMAT_S16_BE, |
| 1091 #else | 1077 #else |
| 1092 SND_PCM_FORMAT_S16_LE, //format | 1078 SND_PCM_FORMAT_S16_LE, //format |
| 1093 #endif | 1079 #endif |
| 1094 SND_PCM_ACCESS_RW_INTERLEAVED, //access | 1080 SND_PCM_ACCESS_RW_INTERLEAVED, //access |
| 1095 _playChannels, //channels | 1081 _playChannels, //channels |
| 1096 _playoutFreq, //rate | 1082 _playoutFreq, //rate |
| 1097 1, //soft_resample | 1083 1, //soft_resample |
| 1098 ALSA_PLAYOUT_LATENCY //40*1000 //latency required overall latency in us | 1084 ALSA_PLAYOUT_LATENCY //40*1000 //latency required overall latency in us |
| 1099 )) < 0) | 1085 )) < 0) |
| 1100 { /* 0.5sec */ | 1086 { /* 0.5sec */ |
| 1101 _playoutFramesIn10MS = 0; | 1087 _playoutFramesIn10MS = 0; |
| 1102 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, | 1088 LOG(LS_ERROR) << "unable to set playback device: " |
| 1103 " unable to set playback device: %s (%d)", | 1089 << LATE(snd_strerror)(errVal) << " (" << errVal << ")"; |
| 1104 LATE(snd_strerror)(errVal), | |
| 1105 errVal); | |
| 1106 ErrorRecovery(errVal, _handlePlayout); | 1090 ErrorRecovery(errVal, _handlePlayout); |
| 1107 errVal = LATE(snd_pcm_close)(_handlePlayout); | 1091 errVal = LATE(snd_pcm_close)(_handlePlayout); |
| 1108 _handlePlayout = NULL; | 1092 _handlePlayout = NULL; |
| 1109 return -1; | 1093 return -1; |
| 1110 } | 1094 } |
| 1111 | 1095 |
| 1112 errVal = LATE(snd_pcm_get_params)(_handlePlayout, | 1096 errVal = LATE(snd_pcm_get_params)(_handlePlayout, |
| 1113 &_playoutBufferSizeInFrame, &_playoutPeriodSizeInFrame); | 1097 &_playoutBufferSizeInFrame, &_playoutPeriodSizeInFrame); |
| 1114 if (errVal < 0) | 1098 if (errVal < 0) |
| 1115 { | 1099 { |
| 1116 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, | 1100 LOG(LS_ERROR) << "snd_pcm_get_params: " << LATE(snd_strerror)(errVal) |
| 1117 " snd_pcm_get_params %s", | 1101 << " (" << errVal << ")"; |
| 1118 LATE(snd_strerror)(errVal), | |
| 1119 errVal); | |
| 1120 _playoutBufferSizeInFrame = 0; | 1102 _playoutBufferSizeInFrame = 0; |
| 1121 _playoutPeriodSizeInFrame = 0; | 1103 _playoutPeriodSizeInFrame = 0; |
| 1122 } | 1104 } |
| 1123 else { | 1105 else { |
| 1124 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, | 1106 LOG(LS_VERBOSE) << "playout snd_pcm_get_params buffer_size:" |
| 1125 " playout snd_pcm_get_params " | 1107 << _playoutBufferSizeInFrame << " period_size :" |
| 1126 "buffer_size:%d period_size :%d", | 1108 << _playoutPeriodSizeInFrame; |
| 1127 _playoutBufferSizeInFrame, _playoutPeriodSizeInFrame); | |
| 1128 } | 1109 } |
| 1129 | 1110 |
| 1130 if (_ptrAudioBuffer) | 1111 if (_ptrAudioBuffer) |
| 1131 { | 1112 { |
| 1132 // Update webrtc audio buffer with the selected parameters | 1113 // Update webrtc audio buffer with the selected parameters |
| 1133 _ptrAudioBuffer->SetPlayoutSampleRate(_playoutFreq); | 1114 _ptrAudioBuffer->SetPlayoutSampleRate(_playoutFreq); |
| 1134 _ptrAudioBuffer->SetPlayoutChannels(_playChannels); | 1115 _ptrAudioBuffer->SetPlayoutChannels(_playChannels); |
| 1135 } | 1116 } |
| 1136 | 1117 |
| 1137 // Set play buffer size | 1118 // Set play buffer size |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1173 } | 1154 } |
| 1174 | 1155 |
| 1175 if (_recIsInitialized) | 1156 if (_recIsInitialized) |
| 1176 { | 1157 { |
| 1177 return 0; | 1158 return 0; |
| 1178 } | 1159 } |
| 1179 | 1160 |
| 1180 // Initialize the microphone (devices might have been added or removed) | 1161 // Initialize the microphone (devices might have been added or removed) |
| 1181 if (InitMicrophone() == -1) | 1162 if (InitMicrophone() == -1) |
| 1182 { | 1163 { |
| 1183 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, | 1164 LOG(LS_WARNING) << "InitMicrophone() failed"; |
| 1184 " InitMicrophone() failed"); | |
| 1185 } | 1165 } |
| 1186 | 1166 |
| 1187 // Start by closing any existing pcm-input devices | 1167 // Start by closing any existing pcm-input devices |
| 1188 // | 1168 // |
| 1189 if (_handleRecord != NULL) | 1169 if (_handleRecord != NULL) |
| 1190 { | 1170 { |
| 1191 int errVal = LATE(snd_pcm_close)(_handleRecord); | 1171 int errVal = LATE(snd_pcm_close)(_handleRecord); |
| 1192 _handleRecord = NULL; | 1172 _handleRecord = NULL; |
| 1193 _recIsInitialized = false; | 1173 _recIsInitialized = false; |
| 1194 if (errVal < 0) | 1174 if (errVal < 0) |
| 1195 { | 1175 { |
| 1196 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, | 1176 LOG(LS_ERROR) |
| 1197 " Error closing current recording sound device," | 1177 << "Error closing current recording sound device, error: " |
| 1198 " error: %s", | 1178 << LATE(snd_strerror)(errVal); |
| 1199 LATE(snd_strerror)(errVal)); | |
| 1200 } | 1179 } |
| 1201 } | 1180 } |
| 1202 | 1181 |
| 1203 // Open PCM device for recording | 1182 // Open PCM device for recording |
| 1204 // The corresponding settings for playout are made after the record settings | 1183 // The corresponding settings for playout are made after the record settings |
| 1205 char deviceName[kAdmMaxDeviceNameSize] = {0}; | 1184 char deviceName[kAdmMaxDeviceNameSize] = {0}; |
| 1206 GetDevicesInfo(2, false, _inputDeviceIndex, deviceName, | 1185 GetDevicesInfo(2, false, _inputDeviceIndex, deviceName, |
| 1207 kAdmMaxDeviceNameSize); | 1186 kAdmMaxDeviceNameSize); |
| 1208 | 1187 |
| 1209 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, | 1188 LOG(LS_VERBOSE) << "InitRecording open (" << deviceName << ")"; |
| 1210 "InitRecording open (%s)", deviceName); | |
| 1211 errVal = LATE(snd_pcm_open) | 1189 errVal = LATE(snd_pcm_open) |
| 1212 (&_handleRecord, | 1190 (&_handleRecord, |
| 1213 deviceName, | 1191 deviceName, |
| 1214 SND_PCM_STREAM_CAPTURE, | 1192 SND_PCM_STREAM_CAPTURE, |
| 1215 SND_PCM_NONBLOCK); | 1193 SND_PCM_NONBLOCK); |
| 1216 | 1194 |
| 1217 // Available modes: 0 = blocking, SND_PCM_NONBLOCK, SND_PCM_ASYNC | 1195 // Available modes: 0 = blocking, SND_PCM_NONBLOCK, SND_PCM_ASYNC |
| 1218 if (errVal == -EBUSY) // Device busy - try some more! | 1196 if (errVal == -EBUSY) // Device busy - try some more! |
| 1219 { | 1197 { |
| 1220 for (int i=0; i < 5; i++) | 1198 for (int i=0; i < 5; i++) |
| 1221 { | 1199 { |
| 1222 SleepMs(1000); | 1200 SleepMs(1000); |
| 1223 errVal = LATE(snd_pcm_open) | 1201 errVal = LATE(snd_pcm_open) |
| 1224 (&_handleRecord, | 1202 (&_handleRecord, |
| 1225 deviceName, | 1203 deviceName, |
| 1226 SND_PCM_STREAM_CAPTURE, | 1204 SND_PCM_STREAM_CAPTURE, |
| 1227 SND_PCM_NONBLOCK); | 1205 SND_PCM_NONBLOCK); |
| 1228 if (errVal == 0) | 1206 if (errVal == 0) |
| 1229 { | 1207 { |
| 1230 break; | 1208 break; |
| 1231 } | 1209 } |
| 1232 } | 1210 } |
| 1233 } | 1211 } |
| 1234 if (errVal < 0) | 1212 if (errVal < 0) |
| 1235 { | 1213 { |
| 1236 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, | 1214 LOG(LS_ERROR) << "unable to open record device: " |
| 1237 " unable to open record device: %s", | 1215 << LATE(snd_strerror)(errVal); |
| 1238 LATE(snd_strerror)(errVal)); | |
| 1239 _handleRecord = NULL; | 1216 _handleRecord = NULL; |
| 1240 return -1; | 1217 return -1; |
| 1241 } | 1218 } |
| 1242 | 1219 |
| 1243 _recordingFramesIn10MS = _recordingFreq/100; | 1220 _recordingFramesIn10MS = _recordingFreq/100; |
| 1244 if ((errVal = LATE(snd_pcm_set_params)(_handleRecord, | 1221 if ((errVal = LATE(snd_pcm_set_params)(_handleRecord, |
| 1245 #if defined(WEBRTC_ARCH_BIG_ENDIAN) | 1222 #if defined(WEBRTC_ARCH_BIG_ENDIAN) |
| 1246 SND_PCM_FORMAT_S16_BE, //format | 1223 SND_PCM_FORMAT_S16_BE, //format |
| 1247 #else | 1224 #else |
| 1248 SND_PCM_FORMAT_S16_LE, //format | 1225 SND_PCM_FORMAT_S16_LE, //format |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1267 SND_PCM_FORMAT_S16_LE, //format | 1244 SND_PCM_FORMAT_S16_LE, //format |
| 1268 #endif | 1245 #endif |
| 1269 SND_PCM_ACCESS_RW_INTERLEAVED, //access | 1246 SND_PCM_ACCESS_RW_INTERLEAVED, //access |
| 1270 _recChannels, //channels | 1247 _recChannels, //channels |
| 1271 _recordingFreq, //rate | 1248 _recordingFreq, //rate |
| 1272 1, //soft_resample | 1249 1, //soft_resample |
| 1273 ALSA_CAPTURE_LATENCY //latency in us | 1250 ALSA_CAPTURE_LATENCY //latency in us |
| 1274 )) < 0) | 1251 )) < 0) |
| 1275 { | 1252 { |
| 1276 _recordingFramesIn10MS = 0; | 1253 _recordingFramesIn10MS = 0; |
| 1277 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, | 1254 LOG(LS_ERROR) << "unable to set record settings: " |
| 1278 " unable to set record settings: %s (%d)", | 1255 << LATE(snd_strerror)(errVal) << " (" << errVal |
| 1279 LATE(snd_strerror)(errVal), errVal); | 1256 << ")"; |
| 1280 ErrorRecovery(errVal, _handleRecord); | 1257 ErrorRecovery(errVal, _handleRecord); |
| 1281 errVal = LATE(snd_pcm_close)(_handleRecord); | 1258 errVal = LATE(snd_pcm_close)(_handleRecord); |
| 1282 _handleRecord = NULL; | 1259 _handleRecord = NULL; |
| 1283 return -1; | 1260 return -1; |
| 1284 } | 1261 } |
| 1285 } | 1262 } |
| 1286 | 1263 |
| 1287 errVal = LATE(snd_pcm_get_params)(_handleRecord, | 1264 errVal = LATE(snd_pcm_get_params)(_handleRecord, |
| 1288 &_recordingBuffersizeInFrame, &_recordingPeriodSizeInFrame); | 1265 &_recordingBuffersizeInFrame, &_recordingPeriodSizeInFrame); |
| 1289 if (errVal < 0) | 1266 if (errVal < 0) |
| 1290 { | 1267 { |
| 1291 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, | 1268 LOG(LS_ERROR) << "snd_pcm_get_params " << LATE(snd_strerror)(errVal) |
| 1292 " snd_pcm_get_params %s", | 1269 << " (" << errVal << ")"; |
| 1293 LATE(snd_strerror)(errVal), errVal); | |
| 1294 _recordingBuffersizeInFrame = 0; | 1270 _recordingBuffersizeInFrame = 0; |
| 1295 _recordingPeriodSizeInFrame = 0; | 1271 _recordingPeriodSizeInFrame = 0; |
| 1296 } | 1272 } |
| 1297 else { | 1273 else { |
| 1298 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, | 1274 LOG(LS_VERBOSE) << "capture snd_pcm_get_params, buffer_size:" |
| 1299 " capture snd_pcm_get_params " | 1275 << _recordingBuffersizeInFrame << ", period_size:" |
| 1300 "buffer_size:%d period_size:%d", | 1276 << _recordingPeriodSizeInFrame; |
| 1301 _recordingBuffersizeInFrame, _recordingPeriodSizeInFrame); | |
| 1302 } | 1277 } |
| 1303 | 1278 |
| 1304 if (_ptrAudioBuffer) | 1279 if (_ptrAudioBuffer) |
| 1305 { | 1280 { |
| 1306 // Update webrtc audio buffer with the selected parameters | 1281 // Update webrtc audio buffer with the selected parameters |
| 1307 _ptrAudioBuffer->SetRecordingSampleRate(_recordingFreq); | 1282 _ptrAudioBuffer->SetRecordingSampleRate(_recordingFreq); |
| 1308 _ptrAudioBuffer->SetRecordingChannels(_recChannels); | 1283 _ptrAudioBuffer->SetRecordingChannels(_recChannels); |
| 1309 } | 1284 } |
| 1310 | 1285 |
| 1311 // Set rec buffer size and create buffer | 1286 // Set rec buffer size and create buffer |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1342 _recording = true; | 1317 _recording = true; |
| 1343 | 1318 |
| 1344 int errVal = 0; | 1319 int errVal = 0; |
| 1345 _recordingFramesLeft = _recordingFramesIn10MS; | 1320 _recordingFramesLeft = _recordingFramesIn10MS; |
| 1346 | 1321 |
| 1347 // Make sure we only create the buffer once. | 1322 // Make sure we only create the buffer once. |
| 1348 if (!_recordingBuffer) | 1323 if (!_recordingBuffer) |
| 1349 _recordingBuffer = new int8_t[_recordingBufferSizeIn10MS]; | 1324 _recordingBuffer = new int8_t[_recordingBufferSizeIn10MS]; |
| 1350 if (!_recordingBuffer) | 1325 if (!_recordingBuffer) |
| 1351 { | 1326 { |
| 1352 WEBRTC_TRACE(kTraceCritical, kTraceAudioDevice, _id, | 1327 LOG(LS_ERROR) << "failed to alloc recording buffer"; |
| 1353 " failed to alloc recording buffer"); | |
| 1354 _recording = false; | 1328 _recording = false; |
| 1355 return -1; | 1329 return -1; |
| 1356 } | 1330 } |
| 1357 // RECORDING | 1331 // RECORDING |
| 1358 _ptrThreadRec.reset(new rtc::PlatformThread( | 1332 _ptrThreadRec.reset(new rtc::PlatformThread( |
| 1359 RecThreadFunc, this, "webrtc_audio_module_capture_thread")); | 1333 RecThreadFunc, this, "webrtc_audio_module_capture_thread")); |
| 1360 | 1334 |
| 1361 _ptrThreadRec->Start(); | 1335 _ptrThreadRec->Start(); |
| 1362 _ptrThreadRec->SetPriority(rtc::kRealtimePriority); | 1336 _ptrThreadRec->SetPriority(rtc::kRealtimePriority); |
| 1363 | 1337 |
| 1364 errVal = LATE(snd_pcm_prepare)(_handleRecord); | 1338 errVal = LATE(snd_pcm_prepare)(_handleRecord); |
| 1365 if (errVal < 0) | 1339 if (errVal < 0) |
| 1366 { | 1340 { |
| 1367 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, | 1341 LOG(LS_ERROR) << "capture snd_pcm_prepare failed (" |
| 1368 " capture snd_pcm_prepare failed (%s)\n", | 1342 << LATE(snd_strerror)(errVal) << ")\n"; |
| 1369 LATE(snd_strerror)(errVal)); | |
| 1370 // just log error | 1343 // just log error |
| 1371 // if snd_pcm_open fails will return -1 | 1344 // if snd_pcm_open fails will return -1 |
| 1372 } | 1345 } |
| 1373 | 1346 |
| 1374 errVal = LATE(snd_pcm_start)(_handleRecord); | 1347 errVal = LATE(snd_pcm_start)(_handleRecord); |
| 1375 if (errVal < 0) | 1348 if (errVal < 0) |
| 1376 { | 1349 { |
| 1377 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, | 1350 LOG(LS_ERROR) << "capture snd_pcm_start err: " |
| 1378 " capture snd_pcm_start err: %s", | 1351 << LATE(snd_strerror)(errVal); |
| 1379 LATE(snd_strerror)(errVal)); | |
| 1380 errVal = LATE(snd_pcm_start)(_handleRecord); | 1352 errVal = LATE(snd_pcm_start)(_handleRecord); |
| 1381 if (errVal < 0) | 1353 if (errVal < 0) |
| 1382 { | 1354 { |
| 1383 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, | 1355 LOG(LS_ERROR) << "capture snd_pcm_start 2nd try err: " |
| 1384 " capture snd_pcm_start 2nd try err: %s", | 1356 << LATE(snd_strerror)(errVal); |
| 1385 LATE(snd_strerror)(errVal)); | |
| 1386 StopRecording(); | 1357 StopRecording(); |
| 1387 return -1; | 1358 return -1; |
| 1388 } | 1359 } |
| 1389 } | 1360 } |
| 1390 | 1361 |
| 1391 return 0; | 1362 return 0; |
| 1392 } | 1363 } |
| 1393 | 1364 |
| 1394 int32_t AudioDeviceLinuxALSA::StopRecording() | 1365 int32_t AudioDeviceLinuxALSA::StopRecording() |
| 1395 { | 1366 { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1423 if (_recordingBuffer) | 1394 if (_recordingBuffer) |
| 1424 { | 1395 { |
| 1425 delete [] _recordingBuffer; | 1396 delete [] _recordingBuffer; |
| 1426 _recordingBuffer = NULL; | 1397 _recordingBuffer = NULL; |
| 1427 } | 1398 } |
| 1428 | 1399 |
| 1429 // Stop and close pcm recording device. | 1400 // Stop and close pcm recording device. |
| 1430 int errVal = LATE(snd_pcm_drop)(_handleRecord); | 1401 int errVal = LATE(snd_pcm_drop)(_handleRecord); |
| 1431 if (errVal < 0) | 1402 if (errVal < 0) |
| 1432 { | 1403 { |
| 1433 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, | 1404 LOG(LS_ERROR) << "Error stop recording: " << LATE(snd_strerror)(errVal); |
| 1434 " Error stop recording: %s", | |
| 1435 LATE(snd_strerror)(errVal)); | |
| 1436 return -1; | 1405 return -1; |
| 1437 } | 1406 } |
| 1438 | 1407 |
| 1439 errVal = LATE(snd_pcm_close)(_handleRecord); | 1408 errVal = LATE(snd_pcm_close)(_handleRecord); |
| 1440 if (errVal < 0) | 1409 if (errVal < 0) |
| 1441 { | 1410 { |
| 1442 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, | 1411 LOG(LS_ERROR) << "Error closing record sound device, error: " |
| 1443 " Error closing record sound device, error: %s", | 1412 << LATE(snd_strerror)(errVal); |
| 1444 LATE(snd_strerror)(errVal)); | |
| 1445 return -1; | 1413 return -1; |
| 1446 } | 1414 } |
| 1447 | 1415 |
| 1448 // Check if we have muted and unmute if so. | 1416 // Check if we have muted and unmute if so. |
| 1449 bool muteEnabled = false; | 1417 bool muteEnabled = false; |
| 1450 MicrophoneMute(muteEnabled); | 1418 MicrophoneMute(muteEnabled); |
| 1451 if (muteEnabled) | 1419 if (muteEnabled) |
| 1452 { | 1420 { |
| 1453 SetMicrophoneMute(false); | 1421 SetMicrophoneMute(false); |
| 1454 } | 1422 } |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1485 return 0; | 1453 return 0; |
| 1486 } | 1454 } |
| 1487 | 1455 |
| 1488 _playing = true; | 1456 _playing = true; |
| 1489 | 1457 |
| 1490 _playoutFramesLeft = 0; | 1458 _playoutFramesLeft = 0; |
| 1491 if (!_playoutBuffer) | 1459 if (!_playoutBuffer) |
| 1492 _playoutBuffer = new int8_t[_playoutBufferSizeIn10MS]; | 1460 _playoutBuffer = new int8_t[_playoutBufferSizeIn10MS]; |
| 1493 if (!_playoutBuffer) | 1461 if (!_playoutBuffer) |
| 1494 { | 1462 { |
| 1495 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, | 1463 LOG(LS_ERROR) << "failed to alloc playout buf"; |
| 1496 " failed to alloc playout buf"); | |
| 1497 _playing = false; | 1464 _playing = false; |
| 1498 return -1; | 1465 return -1; |
| 1499 } | 1466 } |
| 1500 | 1467 |
| 1501 // PLAYOUT | 1468 // PLAYOUT |
| 1502 _ptrThreadPlay.reset(new rtc::PlatformThread( | 1469 _ptrThreadPlay.reset(new rtc::PlatformThread( |
| 1503 PlayThreadFunc, this, "webrtc_audio_module_play_thread")); | 1470 PlayThreadFunc, this, "webrtc_audio_module_play_thread")); |
| 1504 _ptrThreadPlay->Start(); | 1471 _ptrThreadPlay->Start(); |
| 1505 _ptrThreadPlay->SetPriority(rtc::kRealtimePriority); | 1472 _ptrThreadPlay->SetPriority(rtc::kRealtimePriority); |
| 1506 | 1473 |
| 1507 int errVal = LATE(snd_pcm_prepare)(_handlePlayout); | 1474 int errVal = LATE(snd_pcm_prepare)(_handlePlayout); |
| 1508 if (errVal < 0) | 1475 if (errVal < 0) |
| 1509 { | 1476 { |
| 1510 WEBRTC_TRACE(kTraceCritical, kTraceAudioDevice, _id, | 1477 LOG(LS_ERROR) << "playout snd_pcm_prepare failed (" |
| 1511 " playout snd_pcm_prepare failed (%s)\n", | 1478 << LATE(snd_strerror)(errVal) << ")\n"; |
| 1512 LATE(snd_strerror)(errVal)); | |
| 1513 // just log error | 1479 // just log error |
| 1514 // if snd_pcm_open fails will return -1 | 1480 // if snd_pcm_open fails will return -1 |
| 1515 } | 1481 } |
| 1516 | 1482 |
| 1517 return 0; | 1483 return 0; |
| 1518 } | 1484 } |
| 1519 | 1485 |
| 1520 int32_t AudioDeviceLinuxALSA::StopPlayout() | 1486 int32_t AudioDeviceLinuxALSA::StopPlayout() |
| 1521 { | 1487 { |
| 1522 | 1488 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1546 rtc::CritScope lock(&_critSect); | 1512 rtc::CritScope lock(&_critSect); |
| 1547 | 1513 |
| 1548 _playoutFramesLeft = 0; | 1514 _playoutFramesLeft = 0; |
| 1549 delete [] _playoutBuffer; | 1515 delete [] _playoutBuffer; |
| 1550 _playoutBuffer = NULL; | 1516 _playoutBuffer = NULL; |
| 1551 | 1517 |
| 1552 // stop and close pcm playout device | 1518 // stop and close pcm playout device |
| 1553 int errVal = LATE(snd_pcm_drop)(_handlePlayout); | 1519 int errVal = LATE(snd_pcm_drop)(_handlePlayout); |
| 1554 if (errVal < 0) | 1520 if (errVal < 0) |
| 1555 { | 1521 { |
| 1556 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, | 1522 LOG(LS_ERROR) << "Error stop playing: " << LATE(snd_strerror)(errVal); |
| 1557 " Error stop playing: %s", | |
| 1558 LATE(snd_strerror)(errVal)); | |
| 1559 } | 1523 } |
| 1560 | 1524 |
| 1561 errVal = LATE(snd_pcm_close)(_handlePlayout); | 1525 errVal = LATE(snd_pcm_close)(_handlePlayout); |
| 1562 if (errVal < 0) | 1526 if (errVal < 0) |
| 1563 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, | 1527 LOG(LS_ERROR) << "Error closing playout sound device, error: " |
| 1564 " Error closing playout sound device, error: %s", | 1528 << LATE(snd_strerror)(errVal); |
| 1565 LATE(snd_strerror)(errVal)); | |
| 1566 | 1529 |
| 1567 // set the pcm input handle to NULL | 1530 // set the pcm input handle to NULL |
| 1568 _playIsInitialized = false; | 1531 _playIsInitialized = false; |
| 1569 _handlePlayout = NULL; | 1532 _handlePlayout = NULL; |
| 1570 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, | 1533 LOG(LS_VERBOSE) << "handle_playout is now set to NULL"; |
| 1571 " handle_playout is now set to NULL"); | |
| 1572 | 1534 |
| 1573 return 0; | 1535 return 0; |
| 1574 } | 1536 } |
| 1575 | 1537 |
| 1576 int32_t AudioDeviceLinuxALSA::PlayoutDelay(uint16_t& delayMS) const | 1538 int32_t AudioDeviceLinuxALSA::PlayoutDelay(uint16_t& delayMS) const |
| 1577 { | 1539 { |
| 1578 delayMS = (uint16_t)_playoutDelay * 1000 / _playoutFreq; | 1540 delayMS = (uint16_t)_playoutDelay * 1000 / _playoutFreq; |
| 1579 return 0; | 1541 return 0; |
| 1580 } | 1542 } |
| 1581 | 1543 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1619 { | 1581 { |
| 1620 sizeMS = _playBufDelay; | 1582 sizeMS = _playBufDelay; |
| 1621 } | 1583 } |
| 1622 | 1584 |
| 1623 return 0; | 1585 return 0; |
| 1624 } | 1586 } |
| 1625 | 1587 |
| 1626 int32_t AudioDeviceLinuxALSA::CPULoad(uint16_t& load) const | 1588 int32_t AudioDeviceLinuxALSA::CPULoad(uint16_t& load) const |
| 1627 { | 1589 { |
| 1628 | 1590 |
| 1629 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, | 1591 LOG(LS_WARNING) << "API call not supported on this platform"; |
| 1630 " API call not supported on this platform"); | |
| 1631 return -1; | 1592 return -1; |
| 1632 } | 1593 } |
| 1633 | 1594 |
| 1634 bool AudioDeviceLinuxALSA::PlayoutWarning() const | 1595 bool AudioDeviceLinuxALSA::PlayoutWarning() const |
| 1635 { | 1596 { |
| 1636 rtc::CritScope lock(&_critSect); | 1597 rtc::CritScope lock(&_critSect); |
| 1637 return (_playWarning > 0); | 1598 return (_playWarning > 0); |
| 1638 } | 1599 } |
| 1639 | 1600 |
| 1640 bool AudioDeviceLinuxALSA::PlayoutError() const | 1601 bool AudioDeviceLinuxALSA::PlayoutError() const |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1709 // From Chromium issue 95797 | 1670 // From Chromium issue 95797 |
| 1710 // Loop through the sound cards to get Alsa device hints. | 1671 // Loop through the sound cards to get Alsa device hints. |
| 1711 // Don't use snd_device_name_hint(-1,..) since there is a access violation | 1672 // Don't use snd_device_name_hint(-1,..) since there is a access violation |
| 1712 // inside this ALSA API with libasound.so.2.0.0. | 1673 // inside this ALSA API with libasound.so.2.0.0. |
| 1713 int card = -1; | 1674 int card = -1; |
| 1714 while (!(LATE(snd_card_next)(&card)) && (card >= 0) && keepSearching) { | 1675 while (!(LATE(snd_card_next)(&card)) && (card >= 0) && keepSearching) { |
| 1715 void **hints; | 1676 void **hints; |
| 1716 err = LATE(snd_device_name_hint)(card, "pcm", &hints); | 1677 err = LATE(snd_device_name_hint)(card, "pcm", &hints); |
| 1717 if (err != 0) | 1678 if (err != 0) |
| 1718 { | 1679 { |
| 1719 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, | 1680 LOG(LS_ERROR) << "GetDevicesInfo - device name hint error: " |
| 1720 "GetDevicesInfo - device name hint error: %s", | 1681 << LATE(snd_strerror)(err); |
| 1721 LATE(snd_strerror)(err)); | |
| 1722 return -1; | 1682 return -1; |
| 1723 } | 1683 } |
| 1724 | 1684 |
| 1725 enumCount++; // default is 0 | 1685 enumCount++; // default is 0 |
| 1726 if ((function == FUNC_GET_DEVICE_NAME || | 1686 if ((function == FUNC_GET_DEVICE_NAME || |
| 1727 function == FUNC_GET_DEVICE_NAME_FOR_AN_ENUM) && enumDeviceNo == 0) | 1687 function == FUNC_GET_DEVICE_NAME_FOR_AN_ENUM) && enumDeviceNo == 0) |
| 1728 { | 1688 { |
| 1729 strcpy(enumDeviceName, "default"); | 1689 strcpy(enumDeviceName, "default"); |
| 1730 | 1690 |
| 1731 err = LATE(snd_device_name_free_hint)(hints); | 1691 err = LATE(snd_device_name_free_hint)(hints); |
| 1732 if (err != 0) | 1692 if (err != 0) |
| 1733 { | 1693 { |
| 1734 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, | 1694 LOG(LS_ERROR) |
| 1735 "GetDevicesInfo - device name free hint error: %s", | 1695 << "GetDevicesInfo - device name free hint error: " |
| 1736 LATE(snd_strerror)(err)); | 1696 << LATE(snd_strerror)(err); |
| 1737 } | 1697 } |
| 1738 | 1698 |
| 1739 return 0; | 1699 return 0; |
| 1740 } | 1700 } |
| 1741 | 1701 |
| 1742 for (void **list = hints; *list != NULL; ++list) | 1702 for (void **list = hints; *list != NULL; ++list) |
| 1743 { | 1703 { |
| 1744 char *actualType = LATE(snd_device_name_get_hint)(*list, "IOID"); | 1704 char *actualType = LATE(snd_device_name_get_hint)(*list, "IOID"); |
| 1745 if (actualType) | 1705 if (actualType) |
| 1746 { // NULL means it's both. | 1706 { // NULL means it's both. |
| 1747 bool wrongType = (strcmp(actualType, type) != 0); | 1707 bool wrongType = (strcmp(actualType, type) != 0); |
| 1748 free(actualType); | 1708 free(actualType); |
| 1749 if (wrongType) | 1709 if (wrongType) |
| 1750 { | 1710 { |
| 1751 // Wrong type of device (i.e., input vs. output). | 1711 // Wrong type of device (i.e., input vs. output). |
| 1752 continue; | 1712 continue; |
| 1753 } | 1713 } |
| 1754 } | 1714 } |
| 1755 | 1715 |
| 1756 char *name = LATE(snd_device_name_get_hint)(*list, "NAME"); | 1716 char *name = LATE(snd_device_name_get_hint)(*list, "NAME"); |
| 1757 if (!name) | 1717 if (!name) |
| 1758 { | 1718 { |
| 1759 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, | 1719 LOG(LS_ERROR) << "Device has no name"; |
| 1760 "Device has no name"); | |
| 1761 // Skip it. | 1720 // Skip it. |
| 1762 continue; | 1721 continue; |
| 1763 } | 1722 } |
| 1764 | 1723 |
| 1765 // Now check if we actually want to show this device. | 1724 // Now check if we actually want to show this device. |
| 1766 if (strcmp(name, "default") != 0 && | 1725 if (strcmp(name, "default") != 0 && |
| 1767 strcmp(name, "null") != 0 && | 1726 strcmp(name, "null") != 0 && |
| 1768 strcmp(name, "pulse") != 0 && | 1727 strcmp(name, "pulse") != 0 && |
| 1769 strncmp(name, ignorePrefix, strlen(ignorePrefix)) != 0) | 1728 strncmp(name, ignorePrefix, strlen(ignorePrefix)) != 0) |
| 1770 { | 1729 { |
| 1771 // Yes, we do. | 1730 // Yes, we do. |
| 1772 char *desc = LATE(snd_device_name_get_hint)(*list, "DESC"); | 1731 char *desc = LATE(snd_device_name_get_hint)(*list, "DESC"); |
| 1773 if (!desc) | 1732 if (!desc) |
| 1774 { | 1733 { |
| 1775 // Virtual devices don't necessarily have descriptions. | 1734 // Virtual devices don't necessarily have descriptions. |
| 1776 // Use their names instead. | 1735 // Use their names instead. |
| 1777 desc = name; | 1736 desc = name; |
| 1778 } | 1737 } |
| 1779 | 1738 |
| 1780 if (FUNC_GET_NUM_OF_DEVICE == function) | 1739 if (FUNC_GET_NUM_OF_DEVICE == function) |
| 1781 { | 1740 { |
| 1782 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, | 1741 LOG(LS_VERBOSE) << "Enum device " << enumCount << " - " |
| 1783 " Enum device %d - %s", enumCount, name); | 1742 << name; |
| 1784 | 1743 |
| 1785 } | 1744 } |
| 1786 if ((FUNC_GET_DEVICE_NAME == function) && | 1745 if ((FUNC_GET_DEVICE_NAME == function) && |
| 1787 (enumDeviceNo == enumCount)) | 1746 (enumDeviceNo == enumCount)) |
| 1788 { | 1747 { |
| 1789 // We have found the enum device, copy the name to buffer. | 1748 // We have found the enum device, copy the name to buffer. |
| 1790 strncpy(enumDeviceName, desc, ednLen); | 1749 strncpy(enumDeviceName, desc, ednLen); |
| 1791 enumDeviceName[ednLen-1] = '\0'; | 1750 enumDeviceName[ednLen-1] = '\0'; |
| 1792 keepSearching = false; | 1751 keepSearching = false; |
| 1793 // Replace '\n' with '-'. | 1752 // Replace '\n' with '-'. |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1813 | 1772 |
| 1814 free(name); | 1773 free(name); |
| 1815 | 1774 |
| 1816 if (!keepSearching) | 1775 if (!keepSearching) |
| 1817 break; | 1776 break; |
| 1818 } | 1777 } |
| 1819 | 1778 |
| 1820 err = LATE(snd_device_name_free_hint)(hints); | 1779 err = LATE(snd_device_name_free_hint)(hints); |
| 1821 if (err != 0) | 1780 if (err != 0) |
| 1822 { | 1781 { |
| 1823 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, | 1782 LOG(LS_ERROR) << "GetDevicesInfo - device name free hint error: " |
| 1824 "GetDevicesInfo - device name free hint error: %s", | 1783 << LATE(snd_strerror)(err); |
| 1825 LATE(snd_strerror)(err)); | |
| 1826 // Continue and return true anyway, since we did get the whole list. | 1784 // Continue and return true anyway, since we did get the whole list. |
| 1827 } | 1785 } |
| 1828 } | 1786 } |
| 1829 | 1787 |
| 1830 if (FUNC_GET_NUM_OF_DEVICE == function) | 1788 if (FUNC_GET_NUM_OF_DEVICE == function) |
| 1831 { | 1789 { |
| 1832 if (enumCount == 1) // only default? | 1790 if (enumCount == 1) // only default? |
| 1833 enumCount = 0; | 1791 enumCount = 0; |
| 1834 return enumCount; // Normal return point for function 0 | 1792 return enumCount; // Normal return point for function 0 |
| 1835 } | 1793 } |
| 1836 | 1794 |
| 1837 if (keepSearching) | 1795 if (keepSearching) |
| 1838 { | 1796 { |
| 1839 // If we get here for function 1 and 2, we didn't find the specified | 1797 // If we get here for function 1 and 2, we didn't find the specified |
| 1840 // enum device. | 1798 // enum device. |
| 1841 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, | 1799 LOG(LS_ERROR) |
| 1842 "GetDevicesInfo - Could not find device name or numbers"); | 1800 << "GetDevicesInfo - Could not find device name or numbers"; |
| 1843 return -1; | 1801 return -1; |
| 1844 } | 1802 } |
| 1845 | 1803 |
| 1846 return 0; | 1804 return 0; |
| 1847 } | 1805 } |
| 1848 | 1806 |
| 1849 int32_t AudioDeviceLinuxALSA::InputSanityCheckAfterUnlockedPeriod() const | 1807 int32_t AudioDeviceLinuxALSA::InputSanityCheckAfterUnlockedPeriod() const |
| 1850 { | 1808 { |
| 1851 if (_handleRecord == NULL) | 1809 if (_handleRecord == NULL) |
| 1852 { | 1810 { |
| 1853 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, | 1811 LOG(LS_ERROR) << "input state has been modified during unlocked period"; |
| 1854 " input state has been modified during unlocked period"); | |
| 1855 return -1; | 1812 return -1; |
| 1856 } | 1813 } |
| 1857 return 0; | 1814 return 0; |
| 1858 } | 1815 } |
| 1859 | 1816 |
| 1860 int32_t AudioDeviceLinuxALSA::OutputSanityCheckAfterUnlockedPeriod() const | 1817 int32_t AudioDeviceLinuxALSA::OutputSanityCheckAfterUnlockedPeriod() const |
| 1861 { | 1818 { |
| 1862 if (_handlePlayout == NULL) | 1819 if (_handlePlayout == NULL) |
| 1863 { | 1820 { |
| 1864 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, | 1821 LOG(LS_ERROR) |
| 1865 " output state has been modified during unlocked period"); | 1822 << "output state has been modified during unlocked period"; |
| 1866 return -1; | 1823 return -1; |
| 1867 } | 1824 } |
| 1868 return 0; | 1825 return 0; |
| 1869 } | 1826 } |
| 1870 | 1827 |
| 1871 int32_t AudioDeviceLinuxALSA::ErrorRecovery(int32_t error, | 1828 int32_t AudioDeviceLinuxALSA::ErrorRecovery(int32_t error, |
| 1872 snd_pcm_t* deviceHandle) | 1829 snd_pcm_t* deviceHandle) |
| 1873 { | 1830 { |
| 1874 int st = LATE(snd_pcm_state)(deviceHandle); | 1831 int st = LATE(snd_pcm_state)(deviceHandle); |
| 1875 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, | 1832 LOG(LS_VERBOSE) << "Trying to recover from " |
| 1876 "Trying to recover from error: %s (%d) (state %d)", | 1833 << ((LATE(snd_pcm_stream)(deviceHandle) == SND_PCM_STREAM_CAPTURE) |
| 1877 (LATE(snd_pcm_stream)(deviceHandle) == SND_PCM_STREAM_CAPTURE) ? | 1834 ? "capture" : "playout") << " error: " << LATE(snd_strerror)(error) |
| 1878 "capture" : "playout", LATE(snd_strerror)(error), error, st); | 1835 << " (" << error << ") (state " << st << ")"; |
| 1879 | 1836 |
| 1880 // It is recommended to use snd_pcm_recover for all errors. If that function | 1837 // It is recommended to use snd_pcm_recover for all errors. If that function |
| 1881 // cannot handle the error, the input error code will be returned, otherwise | 1838 // cannot handle the error, the input error code will be returned, otherwise |
| 1882 // 0 is returned. From snd_pcm_recover API doc: "This functions handles | 1839 // 0 is returned. From snd_pcm_recover API doc: "This functions handles |
| 1883 // -EINTR (4) (interrupted system call), -EPIPE (32) (playout overrun or | 1840 // -EINTR (4) (interrupted system call), -EPIPE (32) (playout overrun or |
| 1884 // capture underrun) and -ESTRPIPE (86) (stream is suspended) error codes | 1841 // capture underrun) and -ESTRPIPE (86) (stream is suspended) error codes |
| 1885 // trying to prepare given stream for next I/O." | 1842 // trying to prepare given stream for next I/O." |
| 1886 | 1843 |
| 1887 /** Open */ | 1844 /** Open */ |
| 1888 // SND_PCM_STATE_OPEN = 0, | 1845 // SND_PCM_STATE_OPEN = 0, |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1903 // ** Hardware is disconnected */ | 1860 // ** Hardware is disconnected */ |
| 1904 // SND_PCM_STATE_DISCONNECTED, | 1861 // SND_PCM_STATE_DISCONNECTED, |
| 1905 // SND_PCM_STATE_LAST = SND_PCM_STATE_DISCONNECTED | 1862 // SND_PCM_STATE_LAST = SND_PCM_STATE_DISCONNECTED |
| 1906 | 1863 |
| 1907 // snd_pcm_recover isn't available in older alsa, e.g. on the FC4 machine | 1864 // snd_pcm_recover isn't available in older alsa, e.g. on the FC4 machine |
| 1908 // in Sthlm lab. | 1865 // in Sthlm lab. |
| 1909 | 1866 |
| 1910 int res = LATE(snd_pcm_recover)(deviceHandle, error, 1); | 1867 int res = LATE(snd_pcm_recover)(deviceHandle, error, 1); |
| 1911 if (0 == res) | 1868 if (0 == res) |
| 1912 { | 1869 { |
| 1913 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, | 1870 LOG(LS_VERBOSE) << "Recovery - snd_pcm_recover OK"; |
| 1914 " Recovery - snd_pcm_recover OK"); | |
| 1915 | 1871 |
| 1916 if ((error == -EPIPE || error == -ESTRPIPE) && // Buf underrun/overrun. | 1872 if ((error == -EPIPE || error == -ESTRPIPE) && // Buf underrun/overrun. |
| 1917 _recording && | 1873 _recording && |
| 1918 LATE(snd_pcm_stream)(deviceHandle) == SND_PCM_STREAM_CAPTURE) | 1874 LATE(snd_pcm_stream)(deviceHandle) == SND_PCM_STREAM_CAPTURE) |
| 1919 { | 1875 { |
| 1920 // For capture streams we also have to repeat the explicit start() | 1876 // For capture streams we also have to repeat the explicit start() |
| 1921 // to get data flowing again. | 1877 // to get data flowing again. |
| 1922 int err = LATE(snd_pcm_start)(deviceHandle); | 1878 int err = LATE(snd_pcm_start)(deviceHandle); |
| 1923 if (err != 0) | 1879 if (err != 0) |
| 1924 { | 1880 { |
| 1925 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, | 1881 LOG(LS_ERROR) << "Recovery - snd_pcm_start error: " << err; |
| 1926 " Recovery - snd_pcm_start error: %u", err); | |
| 1927 return -1; | 1882 return -1; |
| 1928 } | 1883 } |
| 1929 } | 1884 } |
| 1930 | 1885 |
| 1931 if ((error == -EPIPE || error == -ESTRPIPE) && // Buf underrun/overrun. | 1886 if ((error == -EPIPE || error == -ESTRPIPE) && // Buf underrun/overrun. |
| 1932 _playing && | 1887 _playing && |
| 1933 LATE(snd_pcm_stream)(deviceHandle) == SND_PCM_STREAM_PLAYBACK) | 1888 LATE(snd_pcm_stream)(deviceHandle) == SND_PCM_STREAM_PLAYBACK) |
| 1934 { | 1889 { |
| 1935 // For capture streams we also have to repeat the explicit start() t
o get | 1890 // For capture streams we also have to repeat the explicit start() t
o get |
| 1936 // data flowing again. | 1891 // data flowing again. |
| 1937 int err = LATE(snd_pcm_start)(deviceHandle); | 1892 int err = LATE(snd_pcm_start)(deviceHandle); |
| 1938 if (err != 0) | 1893 if (err != 0) |
| 1939 { | 1894 { |
| 1940 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, | 1895 LOG(LS_ERROR) << "Recovery - snd_pcm_start error: " |
| 1941 " Recovery - snd_pcm_start error: %s", | 1896 << LATE(snd_strerror)(err); |
| 1942 LATE(snd_strerror)(err)); | |
| 1943 return -1; | 1897 return -1; |
| 1944 } | 1898 } |
| 1945 } | 1899 } |
| 1946 | 1900 |
| 1947 return -EPIPE == error ? 1 : 0; | 1901 return -EPIPE == error ? 1 : 0; |
| 1948 } | 1902 } |
| 1949 else { | 1903 else { |
| 1950 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, | 1904 LOG(LS_ERROR) << "Unrecoverable alsa stream error: " << res; |
| 1951 " Unrecoverable alsa stream error: %d", res); | |
| 1952 } | 1905 } |
| 1953 | 1906 |
| 1954 return res; | 1907 return res; |
| 1955 } | 1908 } |
| 1956 | 1909 |
| 1957 // ============================================================================ | 1910 // ============================================================================ |
| 1958 // Thread Methods | 1911 // Thread Methods |
| 1959 // ============================================================================ | 1912 // ============================================================================ |
| 1960 | 1913 |
| 1961 bool AudioDeviceLinuxALSA::PlayThreadFunc(void* pThis) | 1914 bool AudioDeviceLinuxALSA::PlayThreadFunc(void* pThis) |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1975 | 1928 |
| 1976 int err; | 1929 int err; |
| 1977 snd_pcm_sframes_t frames; | 1930 snd_pcm_sframes_t frames; |
| 1978 snd_pcm_sframes_t avail_frames; | 1931 snd_pcm_sframes_t avail_frames; |
| 1979 | 1932 |
| 1980 Lock(); | 1933 Lock(); |
| 1981 //return a positive number of frames ready otherwise a negative error code | 1934 //return a positive number of frames ready otherwise a negative error code |
| 1982 avail_frames = LATE(snd_pcm_avail_update)(_handlePlayout); | 1935 avail_frames = LATE(snd_pcm_avail_update)(_handlePlayout); |
| 1983 if (avail_frames < 0) | 1936 if (avail_frames < 0) |
| 1984 { | 1937 { |
| 1985 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, | 1938 LOG(LS_ERROR) << "playout snd_pcm_avail_update error: " |
| 1986 "playout snd_pcm_avail_update error: %s", | 1939 << LATE(snd_strerror)(avail_frames); |
| 1987 LATE(snd_strerror)(avail_frames)); | |
| 1988 ErrorRecovery(avail_frames, _handlePlayout); | 1940 ErrorRecovery(avail_frames, _handlePlayout); |
| 1989 UnLock(); | 1941 UnLock(); |
| 1990 return true; | 1942 return true; |
| 1991 } | 1943 } |
| 1992 else if (avail_frames == 0) | 1944 else if (avail_frames == 0) |
| 1993 { | 1945 { |
| 1994 UnLock(); | 1946 UnLock(); |
| 1995 | 1947 |
| 1996 //maximum tixe in milliseconds to wait, a negative value means infinity | 1948 //maximum tixe in milliseconds to wait, a negative value means infinity |
| 1997 err = LATE(snd_pcm_wait)(_handlePlayout, 2); | 1949 err = LATE(snd_pcm_wait)(_handlePlayout, 2); |
| 1998 if (err == 0) | 1950 if (err == 0) |
| 1999 { //timeout occured | 1951 { //timeout occured |
| 2000 WEBRTC_TRACE(kTraceStream, kTraceAudioDevice, _id, | 1952 LOG(LS_VERBOSE) << "playout snd_pcm_wait timeout"; |
| 2001 "playout snd_pcm_wait timeout"); | |
| 2002 } | 1953 } |
| 2003 | 1954 |
| 2004 return true; | 1955 return true; |
| 2005 } | 1956 } |
| 2006 | 1957 |
| 2007 if (_playoutFramesLeft <= 0) | 1958 if (_playoutFramesLeft <= 0) |
| 2008 { | 1959 { |
| 2009 UnLock(); | 1960 UnLock(); |
| 2010 _ptrAudioBuffer->RequestPlayoutData(_playoutFramesIn10MS); | 1961 _ptrAudioBuffer->RequestPlayoutData(_playoutFramesIn10MS); |
| 2011 Lock(); | 1962 Lock(); |
| 2012 | 1963 |
| 2013 _playoutFramesLeft = _ptrAudioBuffer->GetPlayoutData(_playoutBuffer); | 1964 _playoutFramesLeft = _ptrAudioBuffer->GetPlayoutData(_playoutBuffer); |
| 2014 assert(_playoutFramesLeft == _playoutFramesIn10MS); | 1965 assert(_playoutFramesLeft == _playoutFramesIn10MS); |
| 2015 } | 1966 } |
| 2016 | 1967 |
| 2017 if (static_cast<uint32_t>(avail_frames) > _playoutFramesLeft) | 1968 if (static_cast<uint32_t>(avail_frames) > _playoutFramesLeft) |
| 2018 avail_frames = _playoutFramesLeft; | 1969 avail_frames = _playoutFramesLeft; |
| 2019 | 1970 |
| 2020 int size = LATE(snd_pcm_frames_to_bytes)(_handlePlayout, | 1971 int size = LATE(snd_pcm_frames_to_bytes)(_handlePlayout, |
| 2021 _playoutFramesLeft); | 1972 _playoutFramesLeft); |
| 2022 frames = LATE(snd_pcm_writei)( | 1973 frames = LATE(snd_pcm_writei)( |
| 2023 _handlePlayout, | 1974 _handlePlayout, |
| 2024 &_playoutBuffer[_playoutBufferSizeIn10MS - size], | 1975 &_playoutBuffer[_playoutBufferSizeIn10MS - size], |
| 2025 avail_frames); | 1976 avail_frames); |
| 2026 | 1977 |
| 2027 if (frames < 0) | 1978 if (frames < 0) |
| 2028 { | 1979 { |
| 2029 WEBRTC_TRACE(kTraceStream, kTraceAudioDevice, _id, | 1980 LOG(LS_VERBOSE) << "playout snd_pcm_writei error: " |
| 2030 "playout snd_pcm_writei error: %s", | 1981 << LATE(snd_strerror)(frames); |
| 2031 LATE(snd_strerror)(frames)); | |
| 2032 _playoutFramesLeft = 0; | 1982 _playoutFramesLeft = 0; |
| 2033 ErrorRecovery(frames, _handlePlayout); | 1983 ErrorRecovery(frames, _handlePlayout); |
| 2034 UnLock(); | 1984 UnLock(); |
| 2035 return true; | 1985 return true; |
| 2036 } | 1986 } |
| 2037 else { | 1987 else { |
| 2038 assert(frames==avail_frames); | 1988 assert(frames==avail_frames); |
| 2039 _playoutFramesLeft -= frames; | 1989 _playoutFramesLeft -= frames; |
| 2040 } | 1990 } |
| 2041 | 1991 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2052 snd_pcm_sframes_t frames; | 2002 snd_pcm_sframes_t frames; |
| 2053 snd_pcm_sframes_t avail_frames; | 2003 snd_pcm_sframes_t avail_frames; |
| 2054 int8_t buffer[_recordingBufferSizeIn10MS]; | 2004 int8_t buffer[_recordingBufferSizeIn10MS]; |
| 2055 | 2005 |
| 2056 Lock(); | 2006 Lock(); |
| 2057 | 2007 |
| 2058 //return a positive number of frames ready otherwise a negative error code | 2008 //return a positive number of frames ready otherwise a negative error code |
| 2059 avail_frames = LATE(snd_pcm_avail_update)(_handleRecord); | 2009 avail_frames = LATE(snd_pcm_avail_update)(_handleRecord); |
| 2060 if (avail_frames < 0) | 2010 if (avail_frames < 0) |
| 2061 { | 2011 { |
| 2062 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, | 2012 LOG(LS_ERROR) << "capture snd_pcm_avail_update error: " |
| 2063 "capture snd_pcm_avail_update error: %s", | 2013 << LATE(snd_strerror)(avail_frames); |
| 2064 LATE(snd_strerror)(avail_frames)); | |
| 2065 ErrorRecovery(avail_frames, _handleRecord); | 2014 ErrorRecovery(avail_frames, _handleRecord); |
| 2066 UnLock(); | 2015 UnLock(); |
| 2067 return true; | 2016 return true; |
| 2068 } | 2017 } |
| 2069 else if (avail_frames == 0) | 2018 else if (avail_frames == 0) |
| 2070 { // no frame is available now | 2019 { // no frame is available now |
| 2071 UnLock(); | 2020 UnLock(); |
| 2072 | 2021 |
| 2073 //maximum time in milliseconds to wait, a negative value means infinity | 2022 //maximum time in milliseconds to wait, a negative value means infinity |
| 2074 err = LATE(snd_pcm_wait)(_handleRecord, | 2023 err = LATE(snd_pcm_wait)(_handleRecord, |
| 2075 ALSA_CAPTURE_WAIT_TIMEOUT); | 2024 ALSA_CAPTURE_WAIT_TIMEOUT); |
| 2076 if (err == 0) //timeout occured | 2025 if (err == 0) //timeout occured |
| 2077 WEBRTC_TRACE(kTraceStream, kTraceAudioDevice, _id, | 2026 LOG(LS_VERBOSE) << "capture snd_pcm_wait timeout"; |
| 2078 "capture snd_pcm_wait timeout"); | |
| 2079 | 2027 |
| 2080 return true; | 2028 return true; |
| 2081 } | 2029 } |
| 2082 | 2030 |
| 2083 if (static_cast<uint32_t>(avail_frames) > _recordingFramesLeft) | 2031 if (static_cast<uint32_t>(avail_frames) > _recordingFramesLeft) |
| 2084 avail_frames = _recordingFramesLeft; | 2032 avail_frames = _recordingFramesLeft; |
| 2085 | 2033 |
| 2086 frames = LATE(snd_pcm_readi)(_handleRecord, | 2034 frames = LATE(snd_pcm_readi)(_handleRecord, |
| 2087 buffer, avail_frames); // frames to be written | 2035 buffer, avail_frames); // frames to be written |
| 2088 if (frames < 0) | 2036 if (frames < 0) |
| 2089 { | 2037 { |
| 2090 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, | 2038 LOG(LS_ERROR) << "capture snd_pcm_readi error: " |
| 2091 "capture snd_pcm_readi error: %s", | 2039 << LATE(snd_strerror)(frames); |
| 2092 LATE(snd_strerror)(frames)); | |
| 2093 ErrorRecovery(frames, _handleRecord); | 2040 ErrorRecovery(frames, _handleRecord); |
| 2094 UnLock(); | 2041 UnLock(); |
| 2095 return true; | 2042 return true; |
| 2096 } | 2043 } |
| 2097 else if (frames > 0) | 2044 else if (frames > 0) |
| 2098 { | 2045 { |
| 2099 assert(frames == avail_frames); | 2046 assert(frames == avail_frames); |
| 2100 | 2047 |
| 2101 int left_size = LATE(snd_pcm_frames_to_bytes)(_handleRecord, | 2048 int left_size = LATE(snd_pcm_frames_to_bytes)(_handleRecord, |
| 2102 _recordingFramesLeft); | 2049 _recordingFramesLeft); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2134 _playoutDelay = 0; | 2081 _playoutDelay = 0; |
| 2135 _recordingDelay = 0; | 2082 _recordingDelay = 0; |
| 2136 if (_handlePlayout) | 2083 if (_handlePlayout) |
| 2137 { | 2084 { |
| 2138 err = LATE(snd_pcm_delay)(_handlePlayout, | 2085 err = LATE(snd_pcm_delay)(_handlePlayout, |
| 2139 &_playoutDelay); // returned delay in frames | 2086 &_playoutDelay); // returned delay in frames |
| 2140 if (err < 0) | 2087 if (err < 0) |
| 2141 { | 2088 { |
| 2142 // TODO(xians): Shall we call ErrorRecovery() here? | 2089 // TODO(xians): Shall we call ErrorRecovery() here? |
| 2143 _playoutDelay = 0; | 2090 _playoutDelay = 0; |
| 2144 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, | 2091 LOG(LS_ERROR) << "playout snd_pcm_delay: " |
| 2145 "playout snd_pcm_delay: %s", | 2092 << LATE(snd_strerror)(err); |
| 2146 LATE(snd_strerror)(err)); | |
| 2147 } | 2093 } |
| 2148 } | 2094 } |
| 2149 | 2095 |
| 2150 err = LATE(snd_pcm_delay)(_handleRecord, | 2096 err = LATE(snd_pcm_delay)(_handleRecord, |
| 2151 &_recordingDelay); // returned delay in frames | 2097 &_recordingDelay); // returned delay in frames |
| 2152 if (err < 0) | 2098 if (err < 0) |
| 2153 { | 2099 { |
| 2154 // TODO(xians): Shall we call ErrorRecovery() here? | 2100 // TODO(xians): Shall we call ErrorRecovery() here? |
| 2155 _recordingDelay = 0; | 2101 _recordingDelay = 0; |
| 2156 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, | 2102 LOG(LS_ERROR) << "capture snd_pcm_delay: " |
| 2157 "capture snd_pcm_delay: %s", | 2103 << LATE(snd_strerror)(err); |
| 2158 LATE(snd_strerror)(err)); | |
| 2159 } | 2104 } |
| 2160 | 2105 |
| 2161 // TODO(xians): Shall we add 10ms buffer delay to the record delay? | 2106 // TODO(xians): Shall we add 10ms buffer delay to the record delay? |
| 2162 _ptrAudioBuffer->SetVQEData( | 2107 _ptrAudioBuffer->SetVQEData( |
| 2163 _playoutDelay * 1000 / _playoutFreq, | 2108 _playoutDelay * 1000 / _playoutFreq, |
| 2164 _recordingDelay * 1000 / _recordingFreq, 0); | 2109 _recordingDelay * 1000 / _recordingFreq, 0); |
| 2165 | 2110 |
| 2166 _ptrAudioBuffer->SetTypingStatus(KeyPressed()); | 2111 _ptrAudioBuffer->SetTypingStatus(KeyPressed()); |
| 2167 | 2112 |
| 2168 // Deliver recorded samples at specified sample rate, mic level etc. | 2113 // Deliver recorded samples at specified sample rate, mic level etc. |
| 2169 // to the observer using callback. | 2114 // to the observer using callback. |
| 2170 UnLock(); | 2115 UnLock(); |
| 2171 _ptrAudioBuffer->DeliverRecordedData(); | 2116 _ptrAudioBuffer->DeliverRecordedData(); |
| 2172 Lock(); | 2117 Lock(); |
| 2173 | 2118 |
| 2174 if (AGC()) | 2119 if (AGC()) |
| 2175 { | 2120 { |
| 2176 newMicLevel = _ptrAudioBuffer->NewMicLevel(); | 2121 newMicLevel = _ptrAudioBuffer->NewMicLevel(); |
| 2177 if (newMicLevel != 0) | 2122 if (newMicLevel != 0) |
| 2178 { | 2123 { |
| 2179 // The VQE will only deliver non-zero microphone levels when
a | 2124 // The VQE will only deliver non-zero microphone levels when
a |
| 2180 // change is needed. Set this new mic level (received from t
he | 2125 // change is needed. Set this new mic level (received from t
he |
| 2181 // observer as return value in the callback). | 2126 // observer as return value in the callback). |
| 2182 if (SetMicrophoneVolume(newMicLevel) == -1) | 2127 if (SetMicrophoneVolume(newMicLevel) == -1) |
| 2183 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, | 2128 LOG(LS_WARNING) |
| 2184 " the required modification of the " | 2129 << "the required modification of the microphone volu
me failed"; |
| 2185 "microphone volume failed"); | |
| 2186 } | 2130 } |
| 2187 } | 2131 } |
| 2188 } | 2132 } |
| 2189 } | 2133 } |
| 2190 | 2134 |
| 2191 UnLock(); | 2135 UnLock(); |
| 2192 return true; | 2136 return true; |
| 2193 } | 2137 } |
| 2194 | 2138 |
| 2195 | 2139 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 2210 state |= (szKey[i] ^ _oldKeyState[i]) & szKey[i]; | 2154 state |= (szKey[i] ^ _oldKeyState[i]) & szKey[i]; |
| 2211 | 2155 |
| 2212 // Save old state | 2156 // Save old state |
| 2213 memcpy((char*)_oldKeyState, (char*)szKey, sizeof(_oldKeyState)); | 2157 memcpy((char*)_oldKeyState, (char*)szKey, sizeof(_oldKeyState)); |
| 2214 return (state != 0); | 2158 return (state != 0); |
| 2215 #else | 2159 #else |
| 2216 return false; | 2160 return false; |
| 2217 #endif | 2161 #endif |
| 2218 } | 2162 } |
| 2219 } // namespace webrtc | 2163 } // namespace webrtc |
| OLD | NEW |