summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/modules/audio_device/win/core_audio_base_win.h
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/libwebrtc/modules/audio_device/win/core_audio_base_win.h')
-rw-r--r--third_party/libwebrtc/modules/audio_device/win/core_audio_base_win.h203
1 files changed, 203 insertions, 0 deletions
diff --git a/third_party/libwebrtc/modules/audio_device/win/core_audio_base_win.h b/third_party/libwebrtc/modules/audio_device/win/core_audio_base_win.h
new file mode 100644
index 0000000000..6c1357e059
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_device/win/core_audio_base_win.h
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_DEVICE_WIN_CORE_AUDIO_BASE_WIN_H_
+#define MODULES_AUDIO_DEVICE_WIN_CORE_AUDIO_BASE_WIN_H_
+
+#include <atomic>
+#include <functional>
+#include <memory>
+#include <string>
+
+#include "absl/strings/string_view.h"
+#include "absl/types/optional.h"
+#include "api/sequence_checker.h"
+#include "modules/audio_device/win/core_audio_utility_win.h"
+#include "rtc_base/platform_thread.h"
+
+namespace webrtc {
+
+class AudioDeviceBuffer;
+class FineAudioBuffer;
+
+namespace webrtc_win {
+
+// Serves as base class for CoreAudioInput and CoreAudioOutput and supports
+// device handling and audio streaming where the direction (input or output)
+// is set at constructions by the parent.
+// The IAudioSessionEvents interface provides notifications of session-related
+// events such as changes in the volume level, display name, and session state.
+// This class does not use the default ref-counting memory management method
+// provided by IUnknown: calling CoreAudioBase::Release() will not delete the
+// object. The client will receive notification from the session manager on
+// a separate thread owned and controlled by the manager.
+// TODO(henrika): investigate if CoreAudioBase should implement
+// IMMNotificationClient as well (might improve support for device changes).
+class CoreAudioBase : public IAudioSessionEvents {
+ public:
+ enum class Direction {
+ kInput,
+ kOutput,
+ };
+
+ // TODO(henrika): add more error types.
+ enum class ErrorType {
+ kStreamDisconnected,
+ };
+
+ template <typename T>
+ auto as_integer(T const value) -> typename std::underlying_type<T>::type {
+ return static_cast<typename std::underlying_type<T>::type>(value);
+ }
+
+ // Callback definition for notifications of new audio data. For input clients,
+ // it means that "new audio data has now been captured", and for output
+ // clients, "the output layer now needs new audio data".
+ typedef std::function<bool(uint64_t device_frequency)> OnDataCallback;
+
+ // Callback definition for notifications of run-time error messages. It can
+ // be called e.g. when an active audio device is removed and an audio stream
+ // is disconnected (`error` is then set to kStreamDisconnected). Both input
+ // and output clients implements OnErrorCallback() and will trigger an
+ // internal restart sequence for kStreamDisconnected.
+ // This method is currently always called on the audio thread.
+ // TODO(henrika): add support for more error types.
+ typedef std::function<bool(ErrorType error)> OnErrorCallback;
+
+ void ThreadRun();
+
+ CoreAudioBase(const CoreAudioBase&) = delete;
+ CoreAudioBase& operator=(const CoreAudioBase&) = delete;
+
+ protected:
+ explicit CoreAudioBase(Direction direction,
+ bool automatic_restart,
+ OnDataCallback data_callback,
+ OnErrorCallback error_callback);
+ ~CoreAudioBase();
+
+ std::string GetDeviceID(int index) const;
+ int SetDevice(int index);
+ int DeviceName(int index, std::string* name, std::string* guid) const;
+
+ // Checks if the current device ID is no longer in use (e.g. due to a
+ // disconnected stream), and if so, switches device to the default audio
+ // device. Called on the audio thread during restart attempts.
+ bool SwitchDeviceIfNeeded();
+
+ bool Init();
+ bool Start();
+ bool Stop();
+ bool IsVolumeControlAvailable(bool* available) const;
+ bool Restart();
+
+ Direction direction() const { return direction_; }
+ bool automatic_restart() const { return automatic_restart_; }
+
+ // Releases all allocated COM resources in the base class.
+ void ReleaseCOMObjects();
+
+ // Returns number of active devices given the specified `direction_` set
+ // by the parent (input or output).
+ int NumberOfActiveDevices() const;
+
+ // Returns total number of enumerated audio devices which is the sum of all
+ // active devices plus two extra (one default and one default
+ // communications). The value in `direction_` determines if capture or
+ // render devices are counted.
+ int NumberOfEnumeratedDevices() const;
+
+ bool IsInput() const;
+ bool IsOutput() const;
+ bool IsDefaultDevice(int index) const;
+ bool IsDefaultCommunicationsDevice(int index) const;
+ bool IsDefaultDeviceId(absl::string_view device_id) const;
+ bool IsDefaultCommunicationsDeviceId(absl::string_view device_id) const;
+ EDataFlow GetDataFlow() const;
+ bool IsRestarting() const;
+ int64_t TimeSinceStart() const;
+
+ // TODO(henrika): is the existing thread checker in WindowsAudioDeviceModule
+ // sufficient? As is, we have one top-level protection and then a second
+ // level here. In addition, calls to Init(), Start() and Stop() are not
+ // included to allow for support of internal restart (where these methods are
+ // called on the audio thread).
+ SequenceChecker thread_checker_;
+ SequenceChecker thread_checker_audio_;
+ AudioDeviceBuffer* audio_device_buffer_ = nullptr;
+ bool initialized_ = false;
+ WAVEFORMATEXTENSIBLE format_ = {};
+ uint32_t endpoint_buffer_size_frames_ = 0;
+ Microsoft::WRL::ComPtr<IAudioClock> audio_clock_;
+ Microsoft::WRL::ComPtr<IAudioClient> audio_client_;
+ bool is_active_ = false;
+ int64_t num_data_callbacks_ = 0;
+ int latency_ms_ = 0;
+ absl::optional<uint32_t> sample_rate_;
+
+ private:
+ const Direction direction_;
+ const bool automatic_restart_;
+ const OnDataCallback on_data_callback_;
+ const OnErrorCallback on_error_callback_;
+ ScopedHandle audio_samples_event_;
+ ScopedHandle stop_event_;
+ ScopedHandle restart_event_;
+ int64_t start_time_ = 0;
+ std::string device_id_;
+ int device_index_ = -1;
+ // Used by the IAudioSessionEvents implementations. Currently only utilized
+ // for debugging purposes.
+ LONG ref_count_ = 1;
+ // Set when restart process starts and cleared when restart stops
+ // successfully. Accessed atomically.
+ std::atomic<bool> is_restarting_;
+ rtc::PlatformThread audio_thread_;
+ Microsoft::WRL::ComPtr<IAudioSessionControl> audio_session_control_;
+
+ void StopThread();
+ AudioSessionState GetAudioSessionState() const;
+
+ // Called on the audio thread when a restart event has been set.
+ // It will then trigger calls to the installed error callbacks with error
+ // type set to kStreamDisconnected.
+ bool HandleRestartEvent();
+
+ // IUnknown (required by IAudioSessionEvents and IMMNotificationClient).
+ ULONG __stdcall AddRef() override;
+ ULONG __stdcall Release() override;
+ HRESULT __stdcall QueryInterface(REFIID iid, void** object) override;
+
+ // IAudioSessionEvents implementation.
+ // These methods are called on separate threads owned by the session manager.
+ // More than one thread can be involved depending on the type of callback
+ // and audio session.
+ HRESULT __stdcall OnStateChanged(AudioSessionState new_state) override;
+ HRESULT __stdcall OnSessionDisconnected(
+ AudioSessionDisconnectReason disconnect_reason) override;
+ HRESULT __stdcall OnDisplayNameChanged(LPCWSTR new_display_name,
+ LPCGUID event_context) override;
+ HRESULT __stdcall OnIconPathChanged(LPCWSTR new_icon_path,
+ LPCGUID event_context) override;
+ HRESULT __stdcall OnSimpleVolumeChanged(float new_simple_volume,
+ BOOL new_mute,
+ LPCGUID event_context) override;
+ HRESULT __stdcall OnChannelVolumeChanged(DWORD channel_count,
+ float new_channel_volumes[],
+ DWORD changed_channel,
+ LPCGUID event_context) override;
+ HRESULT __stdcall OnGroupingParamChanged(LPCGUID new_grouping_param,
+ LPCGUID event_context) override;
+};
+
+} // namespace webrtc_win
+} // namespace webrtc
+
+#endif // MODULES_AUDIO_DEVICE_WIN_CORE_AUDIO_BASE_WIN_H_