• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_UTILITY_WIN_H_
12 #define MODULES_AUDIO_DEVICE_WIN_CORE_AUDIO_UTILITY_WIN_H_
13 
14 #include <audioclient.h>
15 #include <audiopolicy.h>
16 #include <avrt.h>
17 #include <comdef.h>
18 #include <mmdeviceapi.h>
19 #include <objbase.h>
20 #include <propidl.h>
21 #include <wrl/client.h>
22 
23 #include <string>
24 
25 #include "api/units/time_delta.h"
26 #include "modules/audio_device/audio_device_name.h"
27 #include "modules/audio_device/include/audio_device_defines.h"
28 #include "rtc_base/logging.h"
29 #include "rtc_base/string_utils.h"
30 
31 #pragma comment(lib, "Avrt.lib")
32 
33 namespace webrtc {
34 namespace webrtc_win {
35 
36 // Utility class which registers a thread with MMCSS in the constructor and
37 // deregisters MMCSS in the destructor. The task name is given by |task_name|.
38 // The Multimedia Class Scheduler service (MMCSS) enables multimedia
39 // applications to ensure that their time-sensitive processing receives
40 // prioritized access to CPU resources without denying CPU resources to
41 // lower-priority applications.
42 class ScopedMMCSSRegistration {
43  public:
PriorityClassToString(DWORD priority_class)44   const char* PriorityClassToString(DWORD priority_class) {
45     switch (priority_class) {
46       case ABOVE_NORMAL_PRIORITY_CLASS:
47         return "ABOVE_NORMAL";
48       case BELOW_NORMAL_PRIORITY_CLASS:
49         return "BELOW_NORMAL";
50       case HIGH_PRIORITY_CLASS:
51         return "HIGH";
52       case IDLE_PRIORITY_CLASS:
53         return "IDLE";
54       case NORMAL_PRIORITY_CLASS:
55         return "NORMAL";
56       case REALTIME_PRIORITY_CLASS:
57         return "REALTIME";
58       default:
59         return "INVALID";
60     }
61   }
62 
PriorityToString(int priority)63   const char* PriorityToString(int priority) {
64     switch (priority) {
65       case THREAD_PRIORITY_ABOVE_NORMAL:
66         return "ABOVE_NORMAL";
67       case THREAD_PRIORITY_BELOW_NORMAL:
68         return "BELOW_NORMAL";
69       case THREAD_PRIORITY_HIGHEST:
70         return "HIGHEST";
71       case THREAD_PRIORITY_IDLE:
72         return "IDLE";
73       case THREAD_PRIORITY_LOWEST:
74         return "LOWEST";
75       case THREAD_PRIORITY_NORMAL:
76         return "NORMAL";
77       case THREAD_PRIORITY_TIME_CRITICAL:
78         return "TIME_CRITICAL";
79       default:
80         // Can happen in combination with REALTIME_PRIORITY_CLASS.
81         return "INVALID";
82     }
83   }
84 
ScopedMMCSSRegistration(const wchar_t * task_name)85   explicit ScopedMMCSSRegistration(const wchar_t* task_name) {
86     RTC_DLOG(INFO) << "ScopedMMCSSRegistration: " << rtc::ToUtf8(task_name);
87     // Register the calling thread with MMCSS for the supplied |task_name|.
88     DWORD mmcss_task_index = 0;
89     mmcss_handle_ = AvSetMmThreadCharacteristicsW(task_name, &mmcss_task_index);
90     if (mmcss_handle_ == nullptr) {
91       RTC_LOG(LS_ERROR) << "Failed to enable MMCSS on this thread: "
92                         << GetLastError();
93     } else {
94       const DWORD priority_class = GetPriorityClass(GetCurrentProcess());
95       const int priority = GetThreadPriority(GetCurrentThread());
96       RTC_DLOG(INFO) << "priority class: "
97                      << PriorityClassToString(priority_class) << "("
98                      << priority_class << ")";
99       RTC_DLOG(INFO) << "priority: " << PriorityToString(priority) << "("
100                      << priority << ")";
101     }
102   }
103 
~ScopedMMCSSRegistration()104   ~ScopedMMCSSRegistration() {
105     if (Succeeded()) {
106       // Deregister with MMCSS.
107       RTC_DLOG(INFO) << "~ScopedMMCSSRegistration";
108       AvRevertMmThreadCharacteristics(mmcss_handle_);
109     }
110   }
111 
112   ScopedMMCSSRegistration(const ScopedMMCSSRegistration&) = delete;
113   ScopedMMCSSRegistration& operator=(const ScopedMMCSSRegistration&) = delete;
114 
Succeeded()115   bool Succeeded() const { return mmcss_handle_ != nullptr; }
116 
117  private:
118   HANDLE mmcss_handle_ = nullptr;
119 };
120 
121 // Initializes COM in the constructor (STA or MTA), and uninitializes COM in the
122 // destructor. Taken from base::win::ScopedCOMInitializer.
123 //
124 // WARNING: This should only be used once per thread, ideally scoped to a
125 // similar lifetime as the thread itself.  You should not be using this in
126 // random utility functions that make COM calls; instead ensure that these
127 // functions are running on a COM-supporting thread!
128 // See https://msdn.microsoft.com/en-us/library/ms809971.aspx for details.
129 class ScopedCOMInitializer {
130  public:
131   // Enum value provided to initialize the thread as an MTA instead of STA.
132   // There are two types of apartments, Single Threaded Apartments (STAs)
133   // and Multi Threaded Apartments (MTAs). Within a given process there can
134   // be multiple STA’s but there is only one MTA. STA is typically used by
135   // "GUI applications" and MTA by "worker threads" with no UI message loop.
136   enum SelectMTA { kMTA };
137 
138   // Constructor for STA initialization.
ScopedCOMInitializer()139   ScopedCOMInitializer() {
140     RTC_DLOG(INFO) << "Single-Threaded Apartment (STA) COM thread";
141     Initialize(COINIT_APARTMENTTHREADED);
142   }
143 
144   // Constructor for MTA initialization.
ScopedCOMInitializer(SelectMTA mta)145   explicit ScopedCOMInitializer(SelectMTA mta) {
146     RTC_DLOG(INFO) << "Multi-Threaded Apartment (MTA) COM thread";
147     Initialize(COINIT_MULTITHREADED);
148   }
149 
~ScopedCOMInitializer()150   ~ScopedCOMInitializer() {
151     if (Succeeded()) {
152       CoUninitialize();
153     }
154   }
155 
156   ScopedCOMInitializer(const ScopedCOMInitializer&) = delete;
157   ScopedCOMInitializer& operator=(const ScopedCOMInitializer&) = delete;
158 
Succeeded()159   bool Succeeded() { return SUCCEEDED(hr_); }
160 
161  private:
Initialize(COINIT init)162   void Initialize(COINIT init) {
163     // Initializes the COM library for use by the calling thread, sets the
164     // thread's concurrency model, and creates a new apartment for the thread
165     // if one is required. CoInitializeEx must be called at least once, and is
166     // usually called only once, for each thread that uses the COM library.
167     hr_ = CoInitializeEx(NULL, init);
168     RTC_CHECK_NE(RPC_E_CHANGED_MODE, hr_)
169         << "Invalid COM thread model change (MTA->STA)";
170     // Multiple calls to CoInitializeEx by the same thread are allowed as long
171     // as they pass the same concurrency flag, but subsequent valid calls
172     // return S_FALSE. To close the COM library gracefully on a thread, each
173     // successful call to CoInitializeEx, including any call that returns
174     // S_FALSE, must be balanced by a corresponding call to CoUninitialize.
175     if (hr_ == S_OK) {
176       RTC_DLOG(INFO)
177           << "The COM library was initialized successfully on this thread";
178     } else if (hr_ == S_FALSE) {
179       RTC_DLOG(WARNING)
180           << "The COM library is already initialized on this thread";
181     }
182   }
183   HRESULT hr_;
184 };
185 
186 // A PROPVARIANT that is automatically initialized and cleared upon respective
187 // construction and destruction of this class.
188 class ScopedPropVariant {
189  public:
ScopedPropVariant()190   ScopedPropVariant() { PropVariantInit(&pv_); }
191 
~ScopedPropVariant()192   ~ScopedPropVariant() { Reset(); }
193 
194   ScopedPropVariant(const ScopedPropVariant&) = delete;
195   ScopedPropVariant& operator=(const ScopedPropVariant&) = delete;
196   bool operator==(const ScopedPropVariant&) const = delete;
197   bool operator!=(const ScopedPropVariant&) const = delete;
198 
199   // Returns a pointer to the underlying PROPVARIANT for use as an out param in
200   // a function call.
Receive()201   PROPVARIANT* Receive() {
202     RTC_DCHECK_EQ(pv_.vt, VT_EMPTY);
203     return &pv_;
204   }
205 
206   // Clears the instance to prepare it for re-use (e.g., via Receive).
Reset()207   void Reset() {
208     if (pv_.vt != VT_EMPTY) {
209       HRESULT result = PropVariantClear(&pv_);
210       RTC_DCHECK_EQ(result, S_OK);
211     }
212   }
213 
get()214   const PROPVARIANT& get() const { return pv_; }
ptr()215   const PROPVARIANT* ptr() const { return &pv_; }
216 
217  private:
218   PROPVARIANT pv_;
219 };
220 
221 // Simple scoped memory releaser class for COM allocated memory.
222 template <typename T>
223 class ScopedCoMem {
224  public:
ScopedCoMem()225   ScopedCoMem() : mem_ptr_(nullptr) {}
226 
~ScopedCoMem()227   ~ScopedCoMem() { Reset(nullptr); }
228 
229   ScopedCoMem(const ScopedCoMem&) = delete;
230   ScopedCoMem& operator=(const ScopedCoMem&) = delete;
231 
232   T** operator&() {                   // NOLINT
233     RTC_DCHECK(mem_ptr_ == nullptr);  // To catch memory leaks.
234     return &mem_ptr_;
235   }
236 
237   operator T*() { return mem_ptr_; }
238 
239   T* operator->() {
240     RTC_DCHECK(mem_ptr_ != nullptr);
241     return mem_ptr_;
242   }
243 
244   const T* operator->() const {
245     RTC_DCHECK(mem_ptr_ != nullptr);
246     return mem_ptr_;
247   }
248 
249   explicit operator bool() const { return mem_ptr_; }
250 
251   friend bool operator==(const ScopedCoMem& lhs, std::nullptr_t) {
252     return lhs.Get() == nullptr;
253   }
254 
255   friend bool operator==(std::nullptr_t, const ScopedCoMem& rhs) {
256     return rhs.Get() == nullptr;
257   }
258 
259   friend bool operator!=(const ScopedCoMem& lhs, std::nullptr_t) {
260     return lhs.Get() != nullptr;
261   }
262 
263   friend bool operator!=(std::nullptr_t, const ScopedCoMem& rhs) {
264     return rhs.Get() != nullptr;
265   }
266 
Reset(T * ptr)267   void Reset(T* ptr) {
268     if (mem_ptr_)
269       CoTaskMemFree(mem_ptr_);
270     mem_ptr_ = ptr;
271   }
272 
Get()273   T* Get() const { return mem_ptr_; }
274 
275  private:
276   T* mem_ptr_;
277 };
278 
279 // A HANDLE that is automatically initialized and closed upon respective
280 // construction and destruction of this class.
281 class ScopedHandle {
282  public:
ScopedHandle()283   ScopedHandle() : handle_(nullptr) {}
ScopedHandle(HANDLE h)284   explicit ScopedHandle(HANDLE h) : handle_(nullptr) { Set(h); }
285 
~ScopedHandle()286   ~ScopedHandle() { Close(); }
287 
288   ScopedHandle& operator=(const ScopedHandle&) = delete;
289   bool operator==(const ScopedHandle&) const = delete;
290   bool operator!=(const ScopedHandle&) const = delete;
291 
292   // Use this instead of comparing to INVALID_HANDLE_VALUE.
IsValid()293   bool IsValid() const { return handle_ != nullptr; }
294 
Set(HANDLE new_handle)295   void Set(HANDLE new_handle) {
296     Close();
297     // Windows is inconsistent about invalid handles.
298     // See https://blogs.msdn.microsoft.com/oldnewthing/20040302-00/?p=40443
299     // for details.
300     if (new_handle != INVALID_HANDLE_VALUE) {
301       handle_ = new_handle;
302     }
303   }
304 
Get()305   HANDLE Get() const { return handle_; }
306 
HANDLE()307   operator HANDLE() const { return handle_; }
308 
Close()309   void Close() {
310     if (handle_) {
311       if (!::CloseHandle(handle_)) {
312         RTC_NOTREACHED();
313       }
314       handle_ = nullptr;
315     }
316   }
317 
318  private:
319   HANDLE handle_;
320 };
321 
322 // Utility methods for the Core Audio API on Windows.
323 // Always ensure that Core Audio is supported before using these methods.
324 // Use webrtc_win::core_audio_utility::IsSupported() for this purpose.
325 // Also, all methods must be called on a valid COM thread. This can be done
326 // by using the webrtc_win::ScopedCOMInitializer helper class.
327 // These methods are based on media::CoreAudioUtil in Chrome.
328 namespace core_audio_utility {
329 
330 // Helper class which automates casting between WAVEFORMATEX and
331 // WAVEFORMATEXTENSIBLE raw pointers using implicit constructors and
332 // operator overloading. Note that, no memory is allocated by this utility
333 // structure. It only serves as a handle (or a wrapper) of the structure
334 // provided to it at construction.
335 class WaveFormatWrapper {
336  public:
WaveFormatWrapper(WAVEFORMATEXTENSIBLE * p)337   WaveFormatWrapper(WAVEFORMATEXTENSIBLE* p)
338       : ptr_(reinterpret_cast<WAVEFORMATEX*>(p)) {}
WaveFormatWrapper(WAVEFORMATEX * p)339   WaveFormatWrapper(WAVEFORMATEX* p) : ptr_(p) {}
340   ~WaveFormatWrapper() = default;
341 
342   operator WAVEFORMATEX*() const { return ptr_; }
343   WAVEFORMATEX* operator->() const { return ptr_; }
get()344   WAVEFORMATEX* get() const { return ptr_; }
345   WAVEFORMATEXTENSIBLE* GetExtensible() const;
346 
347   bool IsExtensible() const;
348   bool IsPcm() const;
349   bool IsFloat() const;
350   size_t size() const;
351 
352  private:
353   WAVEFORMATEX* ptr_;
354 };
355 
356 // Returns true if Windows Core Audio is supported.
357 // Always verify that this method returns true before using any of the
358 // other methods in this class.
359 bool IsSupported();
360 
361 // Returns true if Multimedia Class Scheduler service (MMCSS) is supported.
362 // The MMCSS enables multimedia applications to ensure that their time-sensitive
363 // processing receives prioritized access to CPU resources without denying CPU
364 // resources to lower-priority applications.
365 bool IsMMCSSSupported();
366 
367 // The MMDevice API lets clients discover the audio endpoint devices in the
368 // system and determine which devices are suitable for the application to use.
369 // Header file Mmdeviceapi.h defines the interfaces in the MMDevice API.
370 
371 // Number of active audio devices in the specified data flow direction.
372 // Set |data_flow| to eAll to retrieve the total number of active audio
373 // devices.
374 int NumberOfActiveDevices(EDataFlow data_flow);
375 
376 // Returns 1, 2, or 3 depending on what version of IAudioClient the platform
377 // supports.
378 // Example: IAudioClient2 is supported on Windows 8 and higher => 2 is returned.
379 uint32_t GetAudioClientVersion();
380 
381 // Creates an IMMDeviceEnumerator interface which provides methods for
382 // enumerating audio endpoint devices.
383 // TODO(henrika): IMMDeviceEnumerator::RegisterEndpointNotificationCallback.
384 Microsoft::WRL::ComPtr<IMMDeviceEnumerator> CreateDeviceEnumerator();
385 
386 // These functions return the unique device id of the default or
387 // communications input/output device, or an empty string if no such device
388 // exists or if the device has been disabled.
389 std::string GetDefaultInputDeviceID();
390 std::string GetDefaultOutputDeviceID();
391 std::string GetCommunicationsInputDeviceID();
392 std::string GetCommunicationsOutputDeviceID();
393 
394 // Creates an IMMDevice interface corresponding to the unique device id in
395 // |device_id|, or by data-flow direction and role if |device_id| is set to
396 // AudioDeviceName::kDefaultDeviceId.
397 Microsoft::WRL::ComPtr<IMMDevice> CreateDevice(const std::string& device_id,
398                                                EDataFlow data_flow,
399                                                ERole role);
400 
401 // Returns the unique ID and user-friendly name of a given endpoint device.
402 // Example: "{0.0.1.00000000}.{8db6020f-18e3-4f25-b6f5-7726c9122574}", and
403 //          "Microphone (Realtek High Definition Audio)".
404 webrtc::AudioDeviceName GetDeviceName(IMMDevice* device);
405 
406 // Gets the user-friendly name of the endpoint device which is represented
407 // by a unique id in |device_id|, or by data-flow direction and role if
408 // |device_id| is set to AudioDeviceName::kDefaultDeviceId.
409 std::string GetFriendlyName(const std::string& device_id,
410                             EDataFlow data_flow,
411                             ERole role);
412 
413 // Query if the audio device is a rendering device or a capture device.
414 EDataFlow GetDataFlow(IMMDevice* device);
415 
416 // Enumerates all input devices and adds the names (friendly name and unique
417 // device id) to the list in |device_names|.
418 bool GetInputDeviceNames(webrtc::AudioDeviceNames* device_names);
419 
420 // Enumerates all output devices and adds the names (friendly name and unique
421 // device id) to the list in |device_names|.
422 bool GetOutputDeviceNames(webrtc::AudioDeviceNames* device_names);
423 
424 // The Windows Audio Session API (WASAPI) enables client applications to
425 // manage the flow of audio data between the application and an audio endpoint
426 // device. Header files Audioclient.h and Audiopolicy.h define the WASAPI
427 // interfaces.
428 
429 // Creates an IAudioSessionManager2 interface for the specified |device|.
430 // This interface provides access to e.g. the IAudioSessionEnumerator
431 Microsoft::WRL::ComPtr<IAudioSessionManager2> CreateSessionManager2(
432     IMMDevice* device);
433 
434 // Creates an IAudioSessionEnumerator interface for the specified |device|.
435 // The client can use the interface to enumerate audio sessions on the audio
436 // device
437 Microsoft::WRL::ComPtr<IAudioSessionEnumerator> CreateSessionEnumerator(
438     IMMDevice* device);
439 
440 // Number of active audio sessions for the given |device|. Expired or inactive
441 // sessions are not included.
442 int NumberOfActiveSessions(IMMDevice* device);
443 
444 // Creates an IAudioClient instance for a specific device or the default
445 // device specified by data-flow direction and role.
446 Microsoft::WRL::ComPtr<IAudioClient> CreateClient(const std::string& device_id,
447                                                   EDataFlow data_flow,
448                                                   ERole role);
449 Microsoft::WRL::ComPtr<IAudioClient2>
450 CreateClient2(const std::string& device_id, EDataFlow data_flow, ERole role);
451 Microsoft::WRL::ComPtr<IAudioClient3>
452 CreateClient3(const std::string& device_id, EDataFlow data_flow, ERole role);
453 
454 // Sets the AudioCategory_Communications category. Should be called before
455 // GetSharedModeMixFormat() and IsFormatSupported(). The |client| argument must
456 // be an IAudioClient2 or IAudioClient3 interface pointer, hence only supported
457 // on Windows 8 and above.
458 // TODO(henrika): evaluate effect (if any).
459 HRESULT SetClientProperties(IAudioClient2* client);
460 
461 // Returns the buffer size limits of the hardware audio engine in
462 // 100-nanosecond units given a specified |format|. Does not require prior
463 // audio stream initialization. The |client| argument must be an IAudioClient2
464 // or IAudioClient3 interface pointer, hence only supported on Windows 8 and
465 // above.
466 // TODO(henrika): always fails with AUDCLNT_E_OFFLOAD_MODE_ONLY.
467 HRESULT GetBufferSizeLimits(IAudioClient2* client,
468                             const WAVEFORMATEXTENSIBLE* format,
469                             REFERENCE_TIME* min_buffer_duration,
470                             REFERENCE_TIME* max_buffer_duration);
471 
472 // Get the mix format that the audio engine uses internally for processing
473 // of shared-mode streams. The client can call this method before calling
474 // IAudioClient::Initialize. When creating a shared-mode stream for an audio
475 // endpoint device, the Initialize method always accepts the stream format
476 // obtained by this method.
477 HRESULT GetSharedModeMixFormat(IAudioClient* client,
478                                WAVEFORMATEXTENSIBLE* format);
479 
480 // Returns true if the specified |client| supports the format in |format|
481 // for the given |share_mode| (shared or exclusive). The client can call this
482 // method before calling IAudioClient::Initialize.
483 bool IsFormatSupported(IAudioClient* client,
484                        AUDCLNT_SHAREMODE share_mode,
485                        const WAVEFORMATEXTENSIBLE* format);
486 
487 // For a shared-mode stream, the audio engine periodically processes the
488 // data in the endpoint buffer at the period obtained in |device_period|.
489 // For an exclusive mode stream, |device_period| corresponds to the minimum
490 // time interval between successive processing by the endpoint device.
491 // This period plus the stream latency between the buffer and endpoint device
492 // represents the minimum possible latency that an audio application can
493 // achieve. The time in |device_period| is expressed in 100-nanosecond units.
494 HRESULT GetDevicePeriod(IAudioClient* client,
495                         AUDCLNT_SHAREMODE share_mode,
496                         REFERENCE_TIME* device_period);
497 
498 // Returns the range of periodicities supported by the engine for the specified
499 // stream |format|. The periodicity of the engine is the rate at which the
500 // engine wakes an event-driven audio client to transfer audio data to or from
501 // the engine. Can be used for low-latency support on some devices.
502 // The |client| argument must be an IAudioClient3 interface pointer, hence only
503 // supported on Windows 10 and above.
504 HRESULT GetSharedModeEnginePeriod(IAudioClient3* client3,
505                                   const WAVEFORMATEXTENSIBLE* format,
506                                   uint32_t* default_period_in_frames,
507                                   uint32_t* fundamental_period_in_frames,
508                                   uint32_t* min_period_in_frames,
509                                   uint32_t* max_period_in_frames);
510 
511 // Get the preferred audio parameters for the given |client| corresponding to
512 // the stream format that the audio engine uses for its internal processing of
513 // shared-mode streams. The acquired values should only be utilized for shared
514 // mode streamed since there are no preferred settings for an exclusive mode
515 // stream.
516 HRESULT GetPreferredAudioParameters(IAudioClient* client,
517                                     webrtc::AudioParameters* params);
518 // As above but override the preferred sample rate and use |sample_rate|
519 // instead. Intended mainly for testing purposes and in combination with rate
520 // conversion.
521 HRESULT GetPreferredAudioParameters(IAudioClient* client,
522                                     webrtc::AudioParameters* params,
523                                     uint32_t sample_rate);
524 
525 // After activating an IAudioClient interface on an audio endpoint device,
526 // the client must initialize it once, and only once, to initialize the audio
527 // stream between the client and the device. In shared mode, the client
528 // connects indirectly through the audio engine which does the mixing.
529 // If a valid event is provided in |event_handle|, the client will be
530 // initialized for event-driven buffer handling. If |event_handle| is set to
531 // nullptr, event-driven buffer handling is not utilized. To achieve the
532 // minimum stream latency between the client application and audio endpoint
533 // device, set |buffer_duration| to 0. A client has the option of requesting a
534 // buffer size that is larger than what is strictly necessary to make timing
535 // glitches rare or nonexistent. Increasing the buffer size does not necessarily
536 // increase the stream latency. Each unit of reference time is 100 nanoseconds.
537 // The |auto_convert_pcm| parameter can be used for testing purposes to ensure
538 // that the sample rate of the client side does not have to match the audio
539 // engine mix format. If |auto_convert_pcm| is set to true, a rate converter
540 // will be inserted to convert between the sample rate in |format| and the
541 // preferred rate given by GetPreferredAudioParameters().
542 // The output parameter |endpoint_buffer_size| contains the size of the
543 // endpoint buffer and it is expressed as the number of audio frames the
544 // buffer can hold.
545 HRESULT SharedModeInitialize(IAudioClient* client,
546                              const WAVEFORMATEXTENSIBLE* format,
547                              HANDLE event_handle,
548                              REFERENCE_TIME buffer_duration,
549                              bool auto_convert_pcm,
550                              uint32_t* endpoint_buffer_size);
551 
552 // Works as SharedModeInitialize() but adds support for using smaller engine
553 // periods than the default period.
554 // The |client| argument must be an IAudioClient3 interface pointer, hence only
555 // supported on Windows 10 and above.
556 // TODO(henrika): can probably be merged into SharedModeInitialize() to avoid
557 // duplicating code. Keeping as separate method for now until decided if we
558 // need low-latency support.
559 HRESULT SharedModeInitializeLowLatency(IAudioClient3* client,
560                                        const WAVEFORMATEXTENSIBLE* format,
561                                        HANDLE event_handle,
562                                        uint32_t period_in_frames,
563                                        bool auto_convert_pcm,
564                                        uint32_t* endpoint_buffer_size);
565 
566 // Creates an IAudioRenderClient client for an existing IAudioClient given by
567 // |client|. The IAudioRenderClient interface enables a client to write
568 // output data to a rendering endpoint buffer. The methods in this interface
569 // manage the movement of data packets that contain audio-rendering data.
570 Microsoft::WRL::ComPtr<IAudioRenderClient> CreateRenderClient(
571     IAudioClient* client);
572 
573 // Creates an IAudioCaptureClient client for an existing IAudioClient given by
574 // |client|. The IAudioCaptureClient interface enables a client to read
575 // input data from a capture endpoint buffer. The methods in this interface
576 // manage the movement of data packets that contain capture data.
577 Microsoft::WRL::ComPtr<IAudioCaptureClient> CreateCaptureClient(
578     IAudioClient* client);
579 
580 // Creates an IAudioClock interface for an existing IAudioClient given by
581 // |client|. The IAudioClock interface enables a client to monitor a stream's
582 // data rate and the current position in the stream.
583 Microsoft::WRL::ComPtr<IAudioClock> CreateAudioClock(IAudioClient* client);
584 
585 // Creates an AudioSessionControl interface for an existing IAudioClient given
586 // by |client|. The IAudioControl interface enables a client to configure the
587 // control parameters for an audio session and to monitor events in the session.
588 Microsoft::WRL::ComPtr<IAudioSessionControl> CreateAudioSessionControl(
589     IAudioClient* client);
590 
591 // Creates an ISimpleAudioVolume interface for an existing IAudioClient given by
592 // |client|. This interface enables a client to control the master volume level
593 // of an active audio session.
594 Microsoft::WRL::ComPtr<ISimpleAudioVolume> CreateSimpleAudioVolume(
595     IAudioClient* client);
596 
597 // Fills up the endpoint rendering buffer with silence for an existing
598 // IAudioClient given by |client| and a corresponding IAudioRenderClient
599 // given by |render_client|.
600 bool FillRenderEndpointBufferWithSilence(IAudioClient* client,
601                                          IAudioRenderClient* render_client);
602 
603 // Prints/logs all fields of the format structure in |format|.
604 // Also supports extended versions (WAVEFORMATEXTENSIBLE).
605 std::string WaveFormatToString(const WaveFormatWrapper format);
606 
607 // Converts Windows internal REFERENCE_TIME (100 nanosecond units) into
608 // generic webrtc::TimeDelta which then can be converted to any time unit.
609 webrtc::TimeDelta ReferenceTimeToTimeDelta(REFERENCE_TIME time);
610 
611 // Converts size expressed in number of audio frames, |num_frames|, into
612 // milliseconds given a specified |sample_rate|.
613 double FramesToMilliseconds(uint32_t num_frames, uint16_t sample_rate);
614 
615 // Converts a COM error into a human-readable string.
616 std::string ErrorToString(const _com_error& error);
617 
618 }  // namespace core_audio_utility
619 }  // namespace webrtc_win
620 }  // namespace webrtc
621 
622 #endif  //  MODULES_AUDIO_DEVICE_WIN_CORE_AUDIO_UTILITY_WIN_H_
623