1 /* 2 * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #ifndef MODULES_AUDIO_DEVICE_WIN_CORE_AUDIO_BASE_WIN_H_ 12 #define MODULES_AUDIO_DEVICE_WIN_CORE_AUDIO_BASE_WIN_H_ 13 14 #include <atomic> 15 #include <functional> 16 #include <memory> 17 #include <string> 18 19 #include "absl/types/optional.h" 20 #include "modules/audio_device/win/core_audio_utility_win.h" 21 #include "rtc_base/platform_thread.h" 22 #include "rtc_base/thread_checker.h" 23 24 namespace webrtc { 25 26 class AudioDeviceBuffer; 27 class FineAudioBuffer; 28 29 namespace webrtc_win { 30 31 // Serves as base class for CoreAudioInput and CoreAudioOutput and supports 32 // device handling and audio streaming where the direction (input or output) 33 // is set at constructions by the parent. 34 // The IAudioSessionEvents interface provides notifications of session-related 35 // events such as changes in the volume level, display name, and session state. 36 // This class does not use the default ref-counting memory management method 37 // provided by IUnknown: calling CoreAudioBase::Release() will not delete the 38 // object. The client will receive notification from the session manager on 39 // a separate thread owned and controlled by the manager. 40 // TODO(henrika): investigate if CoreAudioBase should implement 41 // IMMNotificationClient as well (might improve support for device changes). 42 class CoreAudioBase : public IAudioSessionEvents { 43 public: 44 enum class Direction { 45 kInput, 46 kOutput, 47 }; 48 49 // TODO(henrika): add more error types. 50 enum class ErrorType { 51 kStreamDisconnected, 52 }; 53 54 template <typename T> 55 auto as_integer(T const value) -> typename std::underlying_type<T>::type { 56 return static_cast<typename std::underlying_type<T>::type>(value); 57 } 58 59 // Callback definition for notifications of new audio data. For input clients, 60 // it means that "new audio data has now been captured", and for output 61 // clients, "the output layer now needs new audio data". 62 typedef std::function<bool(uint64_t device_frequency)> OnDataCallback; 63 64 // Callback definition for notifications of run-time error messages. It can 65 // be called e.g. when an active audio device is removed and an audio stream 66 // is disconnected (|error| is then set to kStreamDisconnected). Both input 67 // and output clients implements OnErrorCallback() and will trigger an 68 // internal restart sequence for kStreamDisconnected. 69 // This method is currently always called on the audio thread. 70 // TODO(henrika): add support for more error types. 71 typedef std::function<bool(ErrorType error)> OnErrorCallback; 72 73 void ThreadRun(); 74 75 CoreAudioBase(const CoreAudioBase&) = delete; 76 CoreAudioBase& operator=(const CoreAudioBase&) = delete; 77 78 protected: 79 explicit CoreAudioBase(Direction direction, 80 bool automatic_restart, 81 OnDataCallback data_callback, 82 OnErrorCallback error_callback); 83 ~CoreAudioBase(); 84 85 std::string GetDeviceID(int index) const; 86 int SetDevice(int index); 87 int DeviceName(int index, std::string* name, std::string* guid) const; 88 89 // Checks if the current device ID is no longer in use (e.g. due to a 90 // disconnected stream), and if so, switches device to the default audio 91 // device. Called on the audio thread during restart attempts. 92 bool SwitchDeviceIfNeeded(); 93 94 bool Init(); 95 bool Start(); 96 bool Stop(); 97 bool IsVolumeControlAvailable(bool* available) const; 98 bool Restart(); 99 direction()100 Direction direction() const { return direction_; } automatic_restart()101 bool automatic_restart() const { return automatic_restart_; } 102 103 // Releases all allocated COM resources in the base class. 104 void ReleaseCOMObjects(); 105 106 // Returns number of active devices given the specified |direction_| set 107 // by the parent (input or output). 108 int NumberOfActiveDevices() const; 109 110 // Returns total number of enumerated audio devices which is the sum of all 111 // active devices plus two extra (one default and one default 112 // communications). The value in |direction_| determines if capture or 113 // render devices are counted. 114 int NumberOfEnumeratedDevices() const; 115 116 bool IsInput() const; 117 bool IsOutput() const; 118 bool IsDefaultDevice(int index) const; 119 bool IsDefaultCommunicationsDevice(int index) const; 120 bool IsDefaultDeviceId(const std::string& device_id) const; 121 bool IsDefaultCommunicationsDeviceId(const std::string& device_id) const; 122 EDataFlow GetDataFlow() const; 123 bool IsRestarting() const; 124 int64_t TimeSinceStart() const; 125 126 // TODO(henrika): is the existing thread checker in WindowsAudioDeviceModule 127 // sufficient? As is, we have one top-level protection and then a second 128 // level here. In addition, calls to Init(), Start() and Stop() are not 129 // included to allow for support of internal restart (where these methods are 130 // called on the audio thread). 131 rtc::ThreadChecker thread_checker_; 132 rtc::ThreadChecker thread_checker_audio_; 133 AudioDeviceBuffer* audio_device_buffer_ = nullptr; 134 bool initialized_ = false; 135 WAVEFORMATEXTENSIBLE format_ = {}; 136 uint32_t endpoint_buffer_size_frames_ = 0; 137 Microsoft::WRL::ComPtr<IAudioClock> audio_clock_; 138 Microsoft::WRL::ComPtr<IAudioClient> audio_client_; 139 bool is_active_ = false; 140 int64_t num_data_callbacks_ = 0; 141 int latency_ms_ = 0; 142 absl::optional<uint32_t> sample_rate_; 143 144 private: 145 const Direction direction_; 146 const bool automatic_restart_; 147 const OnDataCallback on_data_callback_; 148 const OnErrorCallback on_error_callback_; 149 ScopedHandle audio_samples_event_; 150 ScopedHandle stop_event_; 151 ScopedHandle restart_event_; 152 int64_t start_time_ = 0; 153 std::string device_id_; 154 int device_index_ = -1; 155 // Used by the IAudioSessionEvents implementations. Currently only utilized 156 // for debugging purposes. 157 LONG ref_count_ = 1; 158 // Set when restart process starts and cleared when restart stops 159 // successfully. Accessed atomically. 160 std::atomic<bool> is_restarting_; 161 std::unique_ptr<rtc::PlatformThread> audio_thread_; 162 Microsoft::WRL::ComPtr<IAudioSessionControl> audio_session_control_; 163 164 void StopThread(); 165 AudioSessionState GetAudioSessionState() const; 166 167 // Called on the audio thread when a restart event has been set. 168 // It will then trigger calls to the installed error callbacks with error 169 // type set to kStreamDisconnected. 170 bool HandleRestartEvent(); 171 172 // IUnknown (required by IAudioSessionEvents and IMMNotificationClient). 173 ULONG __stdcall AddRef() override; 174 ULONG __stdcall Release() override; 175 HRESULT __stdcall QueryInterface(REFIID iid, void** object) override; 176 177 // IAudioSessionEvents implementation. 178 // These methods are called on separate threads owned by the session manager. 179 // More than one thread can be involved depending on the type of callback 180 // and audio session. 181 HRESULT __stdcall OnStateChanged(AudioSessionState new_state) override; 182 HRESULT __stdcall OnSessionDisconnected( 183 AudioSessionDisconnectReason disconnect_reason) override; 184 HRESULT __stdcall OnDisplayNameChanged(LPCWSTR new_display_name, 185 LPCGUID event_context) override; 186 HRESULT __stdcall OnIconPathChanged(LPCWSTR new_icon_path, 187 LPCGUID event_context) override; 188 HRESULT __stdcall OnSimpleVolumeChanged(float new_simple_volume, 189 BOOL new_mute, 190 LPCGUID event_context) override; 191 HRESULT __stdcall OnChannelVolumeChanged(DWORD channel_count, 192 float new_channel_volumes[], 193 DWORD changed_channel, 194 LPCGUID event_context) override; 195 HRESULT __stdcall OnGroupingParamChanged(LPCGUID new_grouping_param, 196 LPCGUID event_context) override; 197 }; 198 199 } // namespace webrtc_win 200 } // namespace webrtc 201 202 #endif // MODULES_AUDIO_DEVICE_WIN_CORE_AUDIO_BASE_WIN_H_ 203