/*
 *  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.
 */

#include "modules/audio_device/win/core_audio_utility_win.h"

#include <Functiondiscoverykeys_devpkey.h>
#include <atlbase.h>
#include <stdio.h>
#include <tchar.h>

#include <iomanip>
#include <string>
#include <utility>

#include "rtc_base/arraysize.h"
#include "rtc_base/logging.h"
#include "rtc_base/platform_thread_types.h"
#include "rtc_base/string_utils.h"
#include "rtc_base/strings/string_builder.h"
#include "rtc_base/win/windows_version.h"

using ATL::CComHeapPtr;
using Microsoft::WRL::ComPtr;
using webrtc::AudioDeviceName;
using webrtc::AudioParameters;

namespace webrtc {
namespace webrtc_win {
namespace {

using core_audio_utility::ErrorToString;

// Converts from channel mask to list of included channels.
// Each audio data format contains channels for one or more of the positions
// listed below. The number of channels simply equals the number of nonzero
// flag bits in the |channel_mask|. The relative positions of the channels
// within each block of audio data always follow the same relative ordering
// as the flag bits in the table below. For example, if |channel_mask| contains
// the value 0x00000033, the format defines four audio channels that are
// assigned for playback to the front-left, front-right, back-left,
// and back-right speakers, respectively. The channel data should be interleaved
// in that order within each block.
std::string ChannelMaskToString(DWORD channel_mask) {
  std::string ss;
  int n = 0;
  if (channel_mask & SPEAKER_FRONT_LEFT) {
    ss += "FRONT_LEFT | ";
    ++n;
  }
  if (channel_mask & SPEAKER_FRONT_RIGHT) {
    ss += "FRONT_RIGHT | ";
    ++n;
  }
  if (channel_mask & SPEAKER_FRONT_CENTER) {
    ss += "FRONT_CENTER | ";
    ++n;
  }
  if (channel_mask & SPEAKER_LOW_FREQUENCY) {
    ss += "LOW_FREQUENCY | ";
    ++n;
  }
  if (channel_mask & SPEAKER_BACK_LEFT) {
    ss += "BACK_LEFT | ";
    ++n;
  }
  if (channel_mask & SPEAKER_BACK_RIGHT) {
    ss += "BACK_RIGHT | ";
    ++n;
  }
  if (channel_mask & SPEAKER_FRONT_LEFT_OF_CENTER) {
    ss += "FRONT_LEFT_OF_CENTER | ";
    ++n;
  }
  if (channel_mask & SPEAKER_FRONT_RIGHT_OF_CENTER) {
    ss += "RIGHT_OF_CENTER | ";
    ++n;
  }
  if (channel_mask & SPEAKER_BACK_CENTER) {
    ss += "BACK_CENTER | ";
    ++n;
  }
  if (channel_mask & SPEAKER_SIDE_LEFT) {
    ss += "SIDE_LEFT | ";
    ++n;
  }
  if (channel_mask & SPEAKER_SIDE_RIGHT) {
    ss += "SIDE_RIGHT | ";
    ++n;
  }
  if (channel_mask & SPEAKER_TOP_CENTER) {
    ss += "TOP_CENTER | ";
    ++n;
  }
  if (channel_mask & SPEAKER_TOP_FRONT_LEFT) {
    ss += "TOP_FRONT_LEFT | ";
    ++n;
  }
  if (channel_mask & SPEAKER_TOP_FRONT_CENTER) {
    ss += "TOP_FRONT_CENTER | ";
    ++n;
  }
  if (channel_mask & SPEAKER_TOP_FRONT_RIGHT) {
    ss += "TOP_FRONT_RIGHT | ";
    ++n;
  }
  if (channel_mask & SPEAKER_TOP_BACK_LEFT) {
    ss += "TOP_BACK_LEFT | ";
    ++n;
  }
  if (channel_mask & SPEAKER_TOP_BACK_CENTER) {
    ss += "TOP_BACK_CENTER | ";
    ++n;
  }
  if (channel_mask & SPEAKER_TOP_BACK_RIGHT) {
    ss += "TOP_BACK_RIGHT | ";
    ++n;
  }

  if (!ss.empty()) {
    // Delete last appended " | " substring.
    ss.erase(ss.end() - 3, ss.end());
  }
  ss += " (";
  ss += std::to_string(n);
  ss += ")";
  return ss;
}

// Converts from channel mask to DirectSound speaker configuration.
// The values below are copied from ksmedia.h.
// Example: KSAUDIO_SPEAKER_STEREO = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT).
const char* DirectSoundConfigToString(DWORD channel_mask) {
  switch (channel_mask) {
    case KSAUDIO_SPEAKER_DIRECTOUT:
      return "KSAUDIO_DIRECTOUT";
    case KSAUDIO_SPEAKER_MONO:
      // Front center (C)
      return "KSAUDIO_MONO";
    case KSAUDIO_SPEAKER_1POINT1:
      return "KSAUDIO_1POINT1";
    case KSAUDIO_SPEAKER_STEREO:
      // Front left (L), front right (R).
      return "KSAUDIO_STEREO";
    case KSAUDIO_SPEAKER_2POINT1:
      return "KSAUDIO_2POINT1";
    case KSAUDIO_SPEAKER_3POINT0:
      return "KSAUDIO_3POINT0";
    case KSAUDIO_SPEAKER_3POINT1:
      return "KSAUDIO_3POINT1";
    case KSAUDIO_SPEAKER_QUAD:
      // L, R, back left (Lb), back right (Rb).
      return "KSAUDIO_QUAD";
    case KSAUDIO_SPEAKER_SURROUND:
      // L, R, front center (C), back center (Cb).
      return "KSAUDIO_SURROUND";
    case KSAUDIO_SPEAKER_5POINT0:
      return "KSAUDIO_5POINT0";
    case KSAUDIO_SPEAKER_5POINT1:
      return "KSAUDIO_5POINT1";
    case KSAUDIO_SPEAKER_7POINT0:
      return "KSAUDIO_7POINT0";
    case KSAUDIO_SPEAKER_7POINT1:
      // L, R, C, Lb, Rb, front left-of-center, front right-of-center, LFE.
      return "KSAUDIO_7POINT1";
    case KSAUDIO_SPEAKER_5POINT1_SURROUND:
      // L, R, C, side left (Ls), side right (Rs), LFE.
      return "KSAUDIO_5POINT1_SURROUND";
    case KSAUDIO_SPEAKER_7POINT1_SURROUND:
      // L, R, C, Lb, Rb, Ls, Rs, LFE.
      return "KSAUDIO_7POINT1_SURROUND";
    default:
      return "KSAUDIO_INVALID";
  }
}

bool LoadAudiosesDll() {
  static const wchar_t* const kAudiosesDLL =
      L"%WINDIR%\\system32\\audioses.dll";
  wchar_t path[MAX_PATH] = {0};
  ExpandEnvironmentStringsW(kAudiosesDLL, path, arraysize(path));
  RTC_DLOG(INFO) << rtc::ToUtf8(path);
  return (LoadLibraryExW(path, nullptr, LOAD_WITH_ALTERED_SEARCH_PATH) !=
          nullptr);
}

bool LoadAvrtDll() {
  static const wchar_t* const kAvrtDLL = L"%WINDIR%\\system32\\Avrt.dll";
  wchar_t path[MAX_PATH] = {0};
  ExpandEnvironmentStringsW(kAvrtDLL, path, arraysize(path));
  RTC_DLOG(INFO) << rtc::ToUtf8(path);
  return (LoadLibraryExW(path, nullptr, LOAD_WITH_ALTERED_SEARCH_PATH) !=
          nullptr);
}

ComPtr<IMMDeviceEnumerator> CreateDeviceEnumeratorInternal(
    bool allow_reinitialize) {
  ComPtr<IMMDeviceEnumerator> device_enumerator;
  _com_error error =
      ::CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_ALL,
                         IID_PPV_ARGS(&device_enumerator));
  if (FAILED(error.Error())) {
    RTC_LOG(LS_ERROR) << "CoCreateInstance failed: " << ErrorToString(error);
  }

  if (error.Error() == CO_E_NOTINITIALIZED && allow_reinitialize) {
    RTC_LOG(LS_ERROR) << "CoCreateInstance failed with CO_E_NOTINITIALIZED";
    // We have seen crashes which indicates that this method can in fact
    // fail with CO_E_NOTINITIALIZED in combination with certain 3rd party
    // modules. Calling CoInitializeEx() is an attempt to resolve the reported
    // issues. See http://crbug.com/378465 for details.
    error = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
    if (FAILED(error.Error())) {
      error = ::CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr,
                                 CLSCTX_ALL, IID_PPV_ARGS(&device_enumerator));
      if (FAILED(error.Error())) {
        RTC_LOG(LS_ERROR) << "CoCreateInstance failed: "
                          << ErrorToString(error);
      }
    }
  }
  return device_enumerator;
}

bool IsSupportedInternal() {
  // The Core Audio APIs are implemented in the user-mode system components
  // Audioses.dll and Mmdevapi.dll. Dependency Walker shows that it is
  // enough to verify possibility to load the Audioses DLL since it depends
  // on Mmdevapi.dll. See http://crbug.com/166397 why this extra step is
  // required to guarantee Core Audio support.
  if (!LoadAudiosesDll())
    return false;

  // Being able to load the Audioses.dll does not seem to be sufficient for
  // all devices to guarantee Core Audio support. To be 100%, we also verify
  // that it is possible to a create the IMMDeviceEnumerator interface. If
  // this works as well we should be home free.
  ComPtr<IMMDeviceEnumerator> device_enumerator =
      CreateDeviceEnumeratorInternal(false);
  if (!device_enumerator) {
    RTC_LOG(LS_ERROR)
        << "Failed to create Core Audio device enumerator on thread with ID "
        << rtc::CurrentThreadId();
    return false;
  }

  return true;
}

bool IsDeviceActive(IMMDevice* device) {
  DWORD state = DEVICE_STATE_DISABLED;
  return SUCCEEDED(device->GetState(&state)) && (state & DEVICE_STATE_ACTIVE);
}

// Retrieve an audio device specified by |device_id| or a default device
// specified by data-flow direction and role if |device_id| is default.
ComPtr<IMMDevice> CreateDeviceInternal(const std::string& device_id,
                                       EDataFlow data_flow,
                                       ERole role) {
  RTC_DLOG(INFO) << "CreateDeviceInternal: " << role;
  ComPtr<IMMDevice> audio_endpoint_device;

  // Create the IMMDeviceEnumerator interface.
  ComPtr<IMMDeviceEnumerator> device_enum(CreateDeviceEnumeratorInternal(true));
  if (!device_enum.Get())
    return audio_endpoint_device;

  _com_error error(S_FALSE);
  if (device_id == AudioDeviceName::kDefaultDeviceId) {
    error = device_enum->GetDefaultAudioEndpoint(
        data_flow, role, audio_endpoint_device.GetAddressOf());
    if (FAILED(error.Error())) {
      RTC_LOG(LS_ERROR)
          << "IMMDeviceEnumerator::GetDefaultAudioEndpoint failed: "
          << ErrorToString(error);
    }
  } else {
    error = device_enum->GetDevice(rtc::ToUtf16(device_id).c_str(),
                                   audio_endpoint_device.GetAddressOf());
    if (FAILED(error.Error())) {
      RTC_LOG(LS_ERROR) << "IMMDeviceEnumerator::GetDevice failed: "
                        << ErrorToString(error);
    }
  }

  // Verify that the audio endpoint device is active, i.e., that the audio
  // adapter that connects to the endpoint device is present and enabled.
  if (SUCCEEDED(error.Error()) &&
      !IsDeviceActive(audio_endpoint_device.Get())) {
    RTC_LOG(LS_WARNING) << "Selected endpoint device is not active";
    audio_endpoint_device.Reset();
  }

  return audio_endpoint_device;
}

std::string GetDeviceIdInternal(IMMDevice* device) {
  // Retrieve unique name of endpoint device.
  // Example: "{0.0.1.00000000}.{8db6020f-18e3-4f25-b6f5-7726c9122574}".
  CComHeapPtr<WCHAR> device_id;
  if (SUCCEEDED(device->GetId(&device_id))) {
    return rtc::ToUtf8(device_id, wcslen(device_id));
  } else {
    return std::string();
  }
}

std::string GetDeviceFriendlyNameInternal(IMMDevice* device) {
  // Retrieve user-friendly name of endpoint device.
  // Example: "Microphone (Realtek High Definition Audio)".
  ComPtr<IPropertyStore> properties;
  HRESULT hr = device->OpenPropertyStore(STGM_READ, properties.GetAddressOf());
  if (FAILED(hr))
    return std::string();

  ScopedPropVariant friendly_name_pv;
  hr = properties->GetValue(PKEY_Device_FriendlyName,
                            friendly_name_pv.Receive());
  if (FAILED(hr))
    return std::string();

  if (friendly_name_pv.get().vt == VT_LPWSTR &&
      friendly_name_pv.get().pwszVal) {
    return rtc::ToUtf8(friendly_name_pv.get().pwszVal,
                       wcslen(friendly_name_pv.get().pwszVal));
  } else {
    return std::string();
  }
}

ComPtr<IAudioSessionManager2> CreateSessionManager2Internal(
    IMMDevice* audio_device) {
  if (!audio_device)
    return ComPtr<IAudioSessionManager2>();

  ComPtr<IAudioSessionManager2> audio_session_manager;
  _com_error error =
      audio_device->Activate(__uuidof(IAudioSessionManager2), CLSCTX_ALL,
                             nullptr, &audio_session_manager);
  if (FAILED(error.Error())) {
    RTC_LOG(LS_ERROR) << "IMMDevice::Activate(IAudioSessionManager2) failed: "
                      << ErrorToString(error);
  }
  return audio_session_manager;
}

ComPtr<IAudioSessionEnumerator> CreateSessionEnumeratorInternal(
    IMMDevice* audio_device) {
  if (!audio_device) {
    return ComPtr<IAudioSessionEnumerator>();
  }

  ComPtr<IAudioSessionEnumerator> audio_session_enumerator;
  ComPtr<IAudioSessionManager2> audio_session_manager =
      CreateSessionManager2Internal(audio_device);
  if (!audio_session_manager.Get()) {
    return audio_session_enumerator;
  }
  _com_error error =
      audio_session_manager->GetSessionEnumerator(&audio_session_enumerator);
  if (FAILED(error.Error())) {
    RTC_LOG(LS_ERROR)
        << "IAudioSessionEnumerator::IAudioSessionEnumerator failed: "
        << ErrorToString(error);
    return ComPtr<IAudioSessionEnumerator>();
  }
  return audio_session_enumerator;
}

// Creates and activates an IAudioClient COM object given the selected
// endpoint device.
ComPtr<IAudioClient> CreateClientInternal(IMMDevice* audio_device) {
  if (!audio_device)
    return ComPtr<IAudioClient>();

  ComPtr<IAudioClient> audio_client;
  _com_error error = audio_device->Activate(__uuidof(IAudioClient), CLSCTX_ALL,
                                            nullptr, &audio_client);
  if (FAILED(error.Error())) {
    RTC_LOG(LS_ERROR) << "IMMDevice::Activate(IAudioClient) failed: "
                      << ErrorToString(error);
  }
  return audio_client;
}

ComPtr<IAudioClient2> CreateClient2Internal(IMMDevice* audio_device) {
  if (!audio_device)
    return ComPtr<IAudioClient2>();

  ComPtr<IAudioClient2> audio_client;
  _com_error error = audio_device->Activate(__uuidof(IAudioClient2), CLSCTX_ALL,
                                            nullptr, &audio_client);
  if (FAILED(error.Error())) {
    RTC_LOG(LS_ERROR) << "IMMDevice::Activate(IAudioClient2) failed: "
                      << ErrorToString(error);
  }
  return audio_client;
}

ComPtr<IAudioClient3> CreateClient3Internal(IMMDevice* audio_device) {
  if (!audio_device)
    return ComPtr<IAudioClient3>();

  ComPtr<IAudioClient3> audio_client;
  _com_error error = audio_device->Activate(__uuidof(IAudioClient3), CLSCTX_ALL,
                                            nullptr, &audio_client);
  if (FAILED(error.Error())) {
    RTC_LOG(LS_ERROR) << "IMMDevice::Activate(IAudioClient3) failed: "
                      << ErrorToString(error);
  }
  return audio_client;
}

ComPtr<IMMDeviceCollection> CreateCollectionInternal(EDataFlow data_flow) {
  ComPtr<IMMDeviceEnumerator> device_enumerator(
      CreateDeviceEnumeratorInternal(true));
  if (!device_enumerator) {
    return ComPtr<IMMDeviceCollection>();
  }

  // Generate a collection of active (present and not disabled) audio endpoint
  // devices for the specified data-flow direction.
  // This method will succeed even if all devices are disabled.
  ComPtr<IMMDeviceCollection> collection;
  _com_error error = device_enumerator->EnumAudioEndpoints(
      data_flow, DEVICE_STATE_ACTIVE, collection.GetAddressOf());
  if (FAILED(error.Error())) {
    RTC_LOG(LS_ERROR) << "IMMDeviceCollection::EnumAudioEndpoints failed: "
                      << ErrorToString(error);
  }
  return collection;
}

bool GetDeviceNamesInternal(EDataFlow data_flow,
                            webrtc::AudioDeviceNames* device_names) {
  // Always add the default device in index 0 and the default communication
  // device as index 1 in the vector. The name of the default device starts
  // with "Default - " and the default communication device starts with
  // "Communication - ".
  //  Example of friendly name: "Default - Headset (SB Arena Headset)"
  ERole role[] = {eConsole, eCommunications};
  ComPtr<IMMDevice> default_device;
  AudioDeviceName default_device_name;
  for (size_t i = 0; i < arraysize(role); ++i) {
    default_device = CreateDeviceInternal(AudioDeviceName::kDefaultDeviceId,
                                          data_flow, role[i]);
    std::string device_name;
    device_name += (role[i] == eConsole ? "Default - " : "Communication - ");
    device_name += GetDeviceFriendlyNameInternal(default_device.Get());
    std::string unique_id = GetDeviceIdInternal(default_device.Get());

    default_device_name.device_name = std::move(device_name);
    default_device_name.unique_id = std::move(unique_id);
    RTC_DLOG(INFO) << "friendly name: " << default_device_name.device_name;
    RTC_DLOG(INFO) << "unique id    : " << default_device_name.unique_id;
    // Add combination of user-friendly and unique name to the output list.
    device_names->emplace_back(default_device_name);
  }

  // Next, add all active input devices on index 2 and above. Note that,
  // one device can have more than one role. Hence, if only one input device
  // is present, the output vector will contain three elements all with the
  // same unique ID but with different names.
  // Example (one capture device but three elements in device_names):
  //   0: friendly name: Default - Headset (SB Arena Headset)
  //   0: unique id    : {0.0.1.00000000}.{822d99bb-d9b0-4f6f-b2a5-cd1be220d338}
  //   1: friendly name: Communication - Headset (SB Arena Headset)
  //   1: unique id    : {0.0.1.00000000}.{822d99bb-d9b0-4f6f-b2a5-cd1be220d338}
  //   2: friendly name: Headset (SB Arena Headset)
  //   2: unique id    : {0.0.1.00000000}.{822d99bb-d9b0-4f6f-b2a5-cd1be220d338}

  // Generate a collection of active audio endpoint devices for the specified
  // direction.
  ComPtr<IMMDeviceCollection> collection = CreateCollectionInternal(data_flow);
  if (!collection.Get()) {
    return false;
  }

  // Retrieve the number of active audio devices for the specified direction.
  UINT number_of_active_devices = 0;
  collection->GetCount(&number_of_active_devices);
  if (number_of_active_devices == 0) {
    return true;
  }

  // Loop over all active devices and add friendly name and unique ID to the
  // |device_names| list which already contains two elements
  RTC_DCHECK_EQ(device_names->size(), 2);
  for (UINT i = 0; i < number_of_active_devices; ++i) {
    // Retrieve a pointer to the specified item in the device collection.
    ComPtr<IMMDevice> audio_device;
    _com_error error = collection->Item(i, audio_device.GetAddressOf());
    if (FAILED(error.Error()))
      continue;
    // Retrieve the complete device name for the given audio device endpoint.
    AudioDeviceName device_name(
        GetDeviceFriendlyNameInternal(audio_device.Get()),
        GetDeviceIdInternal(audio_device.Get()));
    RTC_DLOG(INFO) << "friendly name: " << device_name.device_name;
    RTC_DLOG(INFO) << "unique id    : " << device_name.unique_id;
    // Add combination of user-friendly and unique name to the output list.
    device_names->emplace_back(device_name);
  }

  return true;
}

HRESULT GetPreferredAudioParametersInternal(IAudioClient* client,
                                            AudioParameters* params,
                                            int fixed_sample_rate) {
  WAVEFORMATPCMEX mix_format;
  HRESULT hr = core_audio_utility::GetSharedModeMixFormat(client, &mix_format);
  if (FAILED(hr))
    return hr;

  REFERENCE_TIME default_period = 0;
  hr = core_audio_utility::GetDevicePeriod(client, AUDCLNT_SHAREMODE_SHARED,
                                           &default_period);
  if (FAILED(hr))
    return hr;

  int sample_rate = mix_format.Format.nSamplesPerSec;
  // Override default sample rate if |fixed_sample_rate| is set and different
  // from the default rate.
  if (fixed_sample_rate > 0 && fixed_sample_rate != sample_rate) {
    RTC_DLOG(INFO) << "Using fixed sample rate instead of the preferred: "
                   << sample_rate << " is replaced by " << fixed_sample_rate;
    sample_rate = fixed_sample_rate;
  }
  // TODO(henrika): utilize full mix_format.Format.wBitsPerSample.
  // const size_t bits_per_sample = AudioParameters::kBitsPerSample;
  // TODO(henrika): improve channel layout support.
  const size_t channels = mix_format.Format.nChannels;

  // Use the native device period to derive the smallest possible buffer size
  // in shared mode.
  double device_period_in_seconds =
      static_cast<double>(
          core_audio_utility::ReferenceTimeToTimeDelta(default_period).ms()) /
      1000.0L;
  const size_t frames_per_buffer =
      static_cast<size_t>(sample_rate * device_period_in_seconds + 0.5);

  AudioParameters audio_params(sample_rate, channels, frames_per_buffer);
  *params = audio_params;
  RTC_DLOG(INFO) << audio_params.ToString();

  return hr;
}

}  // namespace

namespace core_audio_utility {

bool IsSupported() {
  RTC_DLOG(INFO) << "IsSupported";
  static bool g_is_supported = IsSupportedInternal();
  return g_is_supported;
}

bool IsMMCSSSupported() {
  RTC_DLOG(INFO) << "IsMMCSSSupported";
  return LoadAvrtDll();
}

int NumberOfActiveDevices(EDataFlow data_flow) {
  // Generate a collection of active audio endpoint devices for the specified
  // data-flow direction.
  ComPtr<IMMDeviceCollection> collection = CreateCollectionInternal(data_flow);
  if (!collection.Get()) {
    return 0;
  }

  // Retrieve the number of active audio devices for the specified direction.
  UINT number_of_active_devices = 0;
  collection->GetCount(&number_of_active_devices);
  std::string str;
  if (data_flow == eCapture) {
    str = "Number of capture devices: ";
  } else if (data_flow == eRender) {
    str = "Number of render devices: ";
  } else if (data_flow == eAll) {
    str = "Total number of devices: ";
  }
  RTC_DLOG(INFO) << str << number_of_active_devices;
  return static_cast<int>(number_of_active_devices);
}

uint32_t GetAudioClientVersion() {
  uint32_t version = 1;
  if (rtc::rtc_win::GetVersion() >= rtc::rtc_win::VERSION_WIN10) {
    version = 3;
  } else if (rtc::rtc_win::GetVersion() >= rtc::rtc_win::VERSION_WIN8) {
    version = 2;
  }
  return version;
}

ComPtr<IMMDeviceEnumerator> CreateDeviceEnumerator() {
  RTC_DLOG(INFO) << "CreateDeviceEnumerator";
  return CreateDeviceEnumeratorInternal(true);
}

std::string GetDefaultInputDeviceID() {
  RTC_DLOG(INFO) << "GetDefaultInputDeviceID";
  ComPtr<IMMDevice> device(
      CreateDevice(AudioDeviceName::kDefaultDeviceId, eCapture, eConsole));
  return device.Get() ? GetDeviceIdInternal(device.Get()) : std::string();
}

std::string GetDefaultOutputDeviceID() {
  RTC_DLOG(INFO) << "GetDefaultOutputDeviceID";
  ComPtr<IMMDevice> device(
      CreateDevice(AudioDeviceName::kDefaultDeviceId, eRender, eConsole));
  return device.Get() ? GetDeviceIdInternal(device.Get()) : std::string();
}

std::string GetCommunicationsInputDeviceID() {
  RTC_DLOG(INFO) << "GetCommunicationsInputDeviceID";
  ComPtr<IMMDevice> device(CreateDevice(AudioDeviceName::kDefaultDeviceId,
                                        eCapture, eCommunications));
  return device.Get() ? GetDeviceIdInternal(device.Get()) : std::string();
}

std::string GetCommunicationsOutputDeviceID() {
  RTC_DLOG(INFO) << "GetCommunicationsOutputDeviceID";
  ComPtr<IMMDevice> device(CreateDevice(AudioDeviceName::kDefaultDeviceId,
                                        eRender, eCommunications));
  return device.Get() ? GetDeviceIdInternal(device.Get()) : std::string();
}

ComPtr<IMMDevice> CreateDevice(const std::string& device_id,
                               EDataFlow data_flow,
                               ERole role) {
  RTC_DLOG(INFO) << "CreateDevice";
  return CreateDeviceInternal(device_id, data_flow, role);
}

AudioDeviceName GetDeviceName(IMMDevice* device) {
  RTC_DLOG(INFO) << "GetDeviceName";
  RTC_DCHECK(device);
  AudioDeviceName device_name(GetDeviceFriendlyNameInternal(device),
                              GetDeviceIdInternal(device));
  RTC_DLOG(INFO) << "friendly name: " << device_name.device_name;
  RTC_DLOG(INFO) << "unique id    : " << device_name.unique_id;
  return device_name;
}

std::string GetFriendlyName(const std::string& device_id,
                            EDataFlow data_flow,
                            ERole role) {
  RTC_DLOG(INFO) << "GetFriendlyName";
  ComPtr<IMMDevice> audio_device = CreateDevice(device_id, data_flow, role);
  if (!audio_device.Get())
    return std::string();

  AudioDeviceName device_name = GetDeviceName(audio_device.Get());
  return device_name.device_name;
}

EDataFlow GetDataFlow(IMMDevice* device) {
  RTC_DLOG(INFO) << "GetDataFlow";
  RTC_DCHECK(device);
  ComPtr<IMMEndpoint> endpoint;
  _com_error error = device->QueryInterface(endpoint.GetAddressOf());
  if (FAILED(error.Error())) {
    RTC_LOG(LS_ERROR) << "IMMDevice::QueryInterface failed: "
                      << ErrorToString(error);
    return eAll;
  }

  EDataFlow data_flow;
  error = endpoint->GetDataFlow(&data_flow);
  if (FAILED(error.Error())) {
    RTC_LOG(LS_ERROR) << "IMMEndpoint::GetDataFlow failed: "
                      << ErrorToString(error);
    return eAll;
  }
  return data_flow;
}

bool GetInputDeviceNames(webrtc::AudioDeviceNames* device_names) {
  RTC_DLOG(INFO) << "GetInputDeviceNames";
  RTC_DCHECK(device_names);
  return GetDeviceNamesInternal(eCapture, device_names);
}

bool GetOutputDeviceNames(webrtc::AudioDeviceNames* device_names) {
  RTC_DLOG(INFO) << "GetOutputDeviceNames";
  RTC_DCHECK(device_names);
  return GetDeviceNamesInternal(eRender, device_names);
}

ComPtr<IAudioSessionManager2> CreateSessionManager2(IMMDevice* device) {
  RTC_DLOG(INFO) << "CreateSessionManager2";
  return CreateSessionManager2Internal(device);
}

Microsoft::WRL::ComPtr<IAudioSessionEnumerator> CreateSessionEnumerator(
    IMMDevice* device) {
  RTC_DLOG(INFO) << "CreateSessionEnumerator";
  return CreateSessionEnumeratorInternal(device);
}

int NumberOfActiveSessions(IMMDevice* device) {
  RTC_DLOG(INFO) << "NumberOfActiveSessions";
  ComPtr<IAudioSessionEnumerator> session_enumerator =
      CreateSessionEnumerator(device);

  // Iterate over all audio sessions for the given device.
  int session_count = 0;
  _com_error error = session_enumerator->GetCount(&session_count);
  if (FAILED(error.Error())) {
    RTC_LOG(LS_ERROR) << "IAudioSessionEnumerator::GetCount failed: "
                      << ErrorToString(error);
    return 0;
  }
  RTC_DLOG(INFO) << "Total number of audio sessions: " << session_count;

  int num_active = 0;
  for (int session = 0; session < session_count; session++) {
    // Acquire the session control interface.
    ComPtr<IAudioSessionControl> session_control;
    error = session_enumerator->GetSession(session, &session_control);
    if (FAILED(error.Error())) {
      RTC_LOG(LS_ERROR) << "IAudioSessionEnumerator::GetSession failed: "
                        << ErrorToString(error);
      return 0;
    }

    // Log the display name of the audio session for debugging purposes.
    CComHeapPtr<WCHAR> display_name;
    if (SUCCEEDED(session_control->GetDisplayName(&display_name))) {
      RTC_DLOG(INFO) << "display name: "
                     << rtc::ToUtf8(display_name, wcslen(display_name));
    }

    // Get the current state and check if the state is active or not.
    AudioSessionState state;
    error = session_control->GetState(&state);
    if (FAILED(error.Error())) {
      RTC_LOG(LS_ERROR) << "IAudioSessionControl::GetState failed: "
                        << ErrorToString(error);
      return 0;
    }
    if (state == AudioSessionStateActive) {
      ++num_active;
    }
  }

  RTC_DLOG(INFO) << "Number of active audio sessions: " << num_active;
  return num_active;
}

ComPtr<IAudioClient> CreateClient(const std::string& device_id,
                                  EDataFlow data_flow,
                                  ERole role) {
  RTC_DLOG(INFO) << "CreateClient";
  ComPtr<IMMDevice> device(CreateDevice(device_id, data_flow, role));
  return CreateClientInternal(device.Get());
}

ComPtr<IAudioClient2> CreateClient2(const std::string& device_id,
                                    EDataFlow data_flow,
                                    ERole role) {
  RTC_DLOG(INFO) << "CreateClient2";
  ComPtr<IMMDevice> device(CreateDevice(device_id, data_flow, role));
  return CreateClient2Internal(device.Get());
}

ComPtr<IAudioClient3> CreateClient3(const std::string& device_id,
                                    EDataFlow data_flow,
                                    ERole role) {
  RTC_DLOG(INFO) << "CreateClient3";
  ComPtr<IMMDevice> device(CreateDevice(device_id, data_flow, role));
  return CreateClient3Internal(device.Get());
}

HRESULT SetClientProperties(IAudioClient2* client) {
  RTC_DLOG(INFO) << "SetClientProperties";
  RTC_DCHECK(client);
  if (GetAudioClientVersion() < 2) {
    RTC_LOG(LS_WARNING) << "Requires IAudioClient2 or higher";
    return AUDCLNT_E_UNSUPPORTED_FORMAT;
  }
  AudioClientProperties props = {0};
  props.cbSize = sizeof(AudioClientProperties);
  // Real-time VoIP communication.
  // TODO(henrika): other categories?
  props.eCategory = AudioCategory_Communications;
  // Hardware-offloaded audio processing allows the main audio processing tasks
  // to be performed outside the computer's main CPU. Check support and log the
  // result but hard-code |bIsOffload| to FALSE for now.
  // TODO(henrika): evaluate hardware-offloading. Might complicate usage of
  // IAudioClient::GetMixFormat().
  BOOL supports_offload = FALSE;
  _com_error error =
      client->IsOffloadCapable(props.eCategory, &supports_offload);
  if (FAILED(error.Error())) {
    RTC_LOG(LS_ERROR) << "IAudioClient2::IsOffloadCapable failed: "
                      << ErrorToString(error);
  }
  RTC_DLOG(INFO) << "supports_offload: " << supports_offload;
  props.bIsOffload = false;
  // TODO(henrika): pros and cons compared with AUDCLNT_STREAMOPTIONS_NONE?
  props.Options |= AUDCLNT_STREAMOPTIONS_NONE;
  // Requires System.Devices.AudioDevice.RawProcessingSupported.
  // The application can choose to *always ignore* the OEM AEC/AGC by setting
  // the AUDCLNT_STREAMOPTIONS_RAW flag in the call to SetClientProperties.
  // This flag will preserve the user experience aspect of Communications
  // streams, but will not insert any OEM provided communications specific
  // processing in the audio signal path.
  // props.Options |= AUDCLNT_STREAMOPTIONS_RAW;

  // If it is important to avoid resampling in the audio engine, set this flag.
  // AUDCLNT_STREAMOPTIONS_MATCH_FORMAT (or anything in IAudioClient3) is not
  // an appropriate interface to use for communications scenarios.
  // This interface is mainly meant for pro audio scenarios.
  // props.Options |= AUDCLNT_STREAMOPTIONS_MATCH_FORMAT;
  RTC_DLOG(INFO) << "options: 0x" << rtc::ToHex(props.Options);
  error = client->SetClientProperties(&props);
  if (FAILED(error.Error())) {
    RTC_LOG(LS_ERROR) << "IAudioClient2::SetClientProperties failed: "
                      << ErrorToString(error);
  }
  return error.Error();
}

HRESULT GetBufferSizeLimits(IAudioClient2* client,
                            const WAVEFORMATEXTENSIBLE* format,
                            REFERENCE_TIME* min_buffer_duration,
                            REFERENCE_TIME* max_buffer_duration) {
  RTC_DLOG(INFO) << "GetBufferSizeLimits";
  RTC_DCHECK(client);
  if (GetAudioClientVersion() < 2) {
    RTC_LOG(LS_WARNING) << "Requires IAudioClient2 or higher";
    return AUDCLNT_E_UNSUPPORTED_FORMAT;
  }
  REFERENCE_TIME min_duration = 0;
  REFERENCE_TIME max_duration = 0;
  _com_error error =
      client->GetBufferSizeLimits(reinterpret_cast<const WAVEFORMATEX*>(format),
                                  TRUE, &min_duration, &max_duration);
  if (error.Error() == AUDCLNT_E_OFFLOAD_MODE_ONLY) {
    // This API seems to be supported in off-load mode only but it is not
    // documented as a valid error code. Making a special note about it here.
    RTC_LOG(LS_ERROR) << "IAudioClient2::GetBufferSizeLimits failed: "
                      << "AUDCLNT_E_OFFLOAD_MODE_ONLY";
  } else if (FAILED(error.Error())) {
    RTC_LOG(LS_ERROR) << "IAudioClient2::GetBufferSizeLimits failed: "
                      << ErrorToString(error);
  } else {
    *min_buffer_duration = min_duration;
    *max_buffer_duration = max_duration;
    RTC_DLOG(INFO) << "min_buffer_duration: " << min_buffer_duration;
    RTC_DLOG(INFO) << "max_buffer_duration: " << max_buffer_duration;
  }
  return error.Error();
}

HRESULT GetSharedModeMixFormat(IAudioClient* client,
                               WAVEFORMATEXTENSIBLE* format) {
  RTC_DLOG(INFO) << "GetSharedModeMixFormat";
  RTC_DCHECK(client);
  ScopedCoMem<WAVEFORMATEXTENSIBLE> format_ex;
  _com_error error =
      client->GetMixFormat(reinterpret_cast<WAVEFORMATEX**>(&format_ex));
  if (FAILED(error.Error())) {
    RTC_LOG(LS_ERROR) << "IAudioClient::GetMixFormat failed: "
                      << ErrorToString(error);
    return error.Error();
  }

  size_t bytes = sizeof(WAVEFORMATEX) + format_ex->Format.cbSize;
  RTC_DCHECK_EQ(bytes, sizeof(WAVEFORMATEXTENSIBLE));
  memcpy(format, format_ex, bytes);
  RTC_DLOG(INFO) << WaveFormatExToString(format);

  return error.Error();
}

bool IsFormatSupported(IAudioClient* client,
                       AUDCLNT_SHAREMODE share_mode,
                       const WAVEFORMATEXTENSIBLE* format) {
  RTC_DLOG(INFO) << "IsFormatSupported";
  RTC_DCHECK(client);
  ScopedCoMem<WAVEFORMATEXTENSIBLE> closest_match;
  // This method provides a way for a client to determine, before calling
  // IAudioClient::Initialize, whether the audio engine supports a particular
  // stream format or not. In shared mode, the audio engine always supports
  // the mix format (see GetSharedModeMixFormat).
  // TODO(henrika): verify support for exclusive mode as well?
  _com_error error = client->IsFormatSupported(
      share_mode, reinterpret_cast<const WAVEFORMATEX*>(format),
      reinterpret_cast<WAVEFORMATEX**>(&closest_match));
  if ((error.Error() == S_OK) && (closest_match == nullptr)) {
    RTC_DLOG(INFO)
        << "The audio endpoint device supports the specified stream format";
  } else if ((error.Error() == S_FALSE) && (closest_match != nullptr)) {
    // Call succeeded with a closest match to the specified format. This log can
    // only be triggered for shared mode.
    RTC_LOG(LS_WARNING)
        << "Exact format is not supported, but a closest match exists";
    RTC_LOG(INFO) << WaveFormatExToString(closest_match);
  } else if ((error.Error() == AUDCLNT_E_UNSUPPORTED_FORMAT) &&
             (closest_match == nullptr)) {
    // The audio engine does not support the caller-specified format or any
    // similar format.
    RTC_DLOG(INFO) << "The audio endpoint device does not support the "
                      "specified stream format";
  } else {
    RTC_LOG(LS_ERROR) << "IAudioClient::IsFormatSupported failed: "
                      << ErrorToString(error);
  }

  return (error.Error() == S_OK);
}

HRESULT GetDevicePeriod(IAudioClient* client,
                        AUDCLNT_SHAREMODE share_mode,
                        REFERENCE_TIME* device_period) {
  RTC_DLOG(INFO) << "GetDevicePeriod";
  RTC_DCHECK(client);
  // The |default_period| parameter specifies the default scheduling period
  // for a shared-mode stream. The |minimum_period| parameter specifies the
  // minimum scheduling period for an exclusive-mode stream.
  // The time is expressed in 100-nanosecond units.
  REFERENCE_TIME default_period = 0;
  REFERENCE_TIME minimum_period = 0;
  _com_error error = client->GetDevicePeriod(&default_period, &minimum_period);
  if (FAILED(error.Error())) {
    RTC_LOG(LS_ERROR) << "IAudioClient::GetDevicePeriod failed: "
                      << ErrorToString(error);
    return error.Error();
  }

  *device_period = (share_mode == AUDCLNT_SHAREMODE_SHARED) ? default_period
                                                            : minimum_period;
  RTC_LOG(INFO) << "device_period: "
                << ReferenceTimeToTimeDelta(*device_period).ms() << " [ms]";
  RTC_LOG(INFO) << "minimum_period: "
                << ReferenceTimeToTimeDelta(minimum_period).ms() << " [ms]";
  return error.Error();
}

HRESULT GetSharedModeEnginePeriod(IAudioClient3* client3,
                                  const WAVEFORMATEXTENSIBLE* format,
                                  uint32_t* default_period_in_frames,
                                  uint32_t* fundamental_period_in_frames,
                                  uint32_t* min_period_in_frames,
                                  uint32_t* max_period_in_frames) {
  RTC_DLOG(INFO) << "GetSharedModeEnginePeriod";
  RTC_DCHECK(client3);

  UINT32 default_period = 0;
  UINT32 fundamental_period = 0;
  UINT32 min_period = 0;
  UINT32 max_period = 0;
  _com_error error = client3->GetSharedModeEnginePeriod(
      reinterpret_cast<const WAVEFORMATEX*>(format), &default_period,
      &fundamental_period, &min_period, &max_period);
  if (FAILED(error.Error())) {
    RTC_LOG(LS_ERROR) << "IAudioClient3::GetSharedModeEnginePeriod failed: "
                      << ErrorToString(error);
    return error.Error();
  }

  WAVEFORMATEX format_ex = format->Format;
  const WORD sample_rate = format_ex.nSamplesPerSec;
  RTC_LOG(INFO) << "default_period_in_frames: " << default_period << " ("
                << FramesToMilliseconds(default_period, sample_rate) << " ms)";
  RTC_LOG(INFO) << "fundamental_period_in_frames: " << fundamental_period
                << " (" << FramesToMilliseconds(fundamental_period, sample_rate)
                << " ms)";
  RTC_LOG(INFO) << "min_period_in_frames: " << min_period << " ("
                << FramesToMilliseconds(min_period, sample_rate) << " ms)";
  RTC_LOG(INFO) << "max_period_in_frames: " << max_period << " ("
                << FramesToMilliseconds(max_period, sample_rate) << " ms)";
  *default_period_in_frames = default_period;
  *fundamental_period_in_frames = fundamental_period;
  *min_period_in_frames = min_period;
  *max_period_in_frames = max_period;
  return error.Error();
}

HRESULT GetPreferredAudioParameters(const std::string& device_id,
                                    bool is_output_device,
                                    AudioParameters* params) {
  RTC_DLOG(INFO) << "GetPreferredAudioParameters: " << is_output_device;
  EDataFlow data_flow = is_output_device ? eRender : eCapture;
  ComPtr<IMMDevice> device;
  if (device_id == AudioDeviceName::kDefaultCommunicationsDeviceId) {
    device = CreateDeviceInternal(AudioDeviceName::kDefaultDeviceId, data_flow,
                                  eCommunications);
  } else {
    // If |device_id| equals AudioDeviceName::kDefaultDeviceId, a default
    // device will be created.
    device = CreateDeviceInternal(device_id, data_flow, eConsole);
  }
  if (!device.Get()) {
    return E_FAIL;
  }

  ComPtr<IAudioClient> client(CreateClientInternal(device.Get()));
  if (!client.Get())
    return E_FAIL;

  return GetPreferredAudioParametersInternal(client.Get(), params, -1);
}

HRESULT GetPreferredAudioParameters(IAudioClient* client,
                                    AudioParameters* params) {
  RTC_DLOG(INFO) << "GetPreferredAudioParameters";
  RTC_DCHECK(client);
  return GetPreferredAudioParametersInternal(client, params, -1);
}

HRESULT GetPreferredAudioParameters(IAudioClient* client,
                                    webrtc::AudioParameters* params,
                                    uint32_t sample_rate) {
  RTC_DLOG(INFO) << "GetPreferredAudioParameters: " << sample_rate;
  RTC_DCHECK(client);
  return GetPreferredAudioParametersInternal(client, params, sample_rate);
}

HRESULT SharedModeInitialize(IAudioClient* client,
                             const WAVEFORMATEXTENSIBLE* format,
                             HANDLE event_handle,
                             REFERENCE_TIME buffer_duration,
                             bool auto_convert_pcm,
                             uint32_t* endpoint_buffer_size) {
  RTC_DLOG(INFO) << "SharedModeInitialize: buffer_duration=" << buffer_duration
                 << ", auto_convert_pcm=" << auto_convert_pcm;
  RTC_DCHECK(client);
  RTC_DCHECK_GE(buffer_duration, 0);
  if (buffer_duration != 0) {
    RTC_DLOG(LS_WARNING) << "Non-default buffer size is used";
  }
  if (auto_convert_pcm) {
    RTC_DLOG(LS_WARNING) << "Sample rate converter can be utilized";
  }
  // The AUDCLNT_STREAMFLAGS_NOPERSIST flag disables persistence of the volume
  // and mute settings for a session that contains rendering streams.
  // By default, the volume level and muting state for a rendering session are
  // persistent across system restarts. The volume level and muting state for a
  // capture session are never persistent.
  DWORD stream_flags = AUDCLNT_STREAMFLAGS_NOPERSIST;

  // Enable event-driven streaming if a valid event handle is provided.
  // After the stream starts, the audio engine will signal the event handle
  // to notify the client each time a buffer becomes ready to process.
  // Event-driven buffering is supported for both rendering and capturing.
  // Both shared-mode and exclusive-mode streams can use event-driven buffering.
  bool use_event =
      (event_handle != nullptr && event_handle != INVALID_HANDLE_VALUE);
  if (use_event) {
    stream_flags |= AUDCLNT_STREAMFLAGS_EVENTCALLBACK;
    RTC_DLOG(INFO) << "The stream is initialized to be event driven";
  }

  // Check if sample-rate conversion is requested.
  if (auto_convert_pcm) {
    // Add channel matrixer (not utilized here) and rate converter to convert
    // from our (the client's) format to the audio engine mix format.
    // Currently only supported for testing, i.e., not possible to enable using
    // public APIs.
    RTC_DLOG(INFO) << "The stream is initialized to support rate conversion";
    stream_flags |= AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM;
    stream_flags |= AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY;
  }
  RTC_DLOG(INFO) << "stream_flags: 0x" << rtc::ToHex(stream_flags);

  // Initialize the shared mode client for minimal delay if |buffer_duration|
  // is 0 or possibly a higher delay (more robust) if |buffer_duration| is
  // larger than 0. The actual size is given by IAudioClient::GetBufferSize().
  _com_error error = client->Initialize(
      AUDCLNT_SHAREMODE_SHARED, stream_flags, buffer_duration, 0,
      reinterpret_cast<const WAVEFORMATEX*>(format), nullptr);
  if (FAILED(error.Error())) {
    RTC_LOG(LS_ERROR) << "IAudioClient::Initialize failed: "
                      << ErrorToString(error);
    return error.Error();
  }

  // If a stream is initialized to be event driven and in shared mode, the
  // associated application must also obtain a handle by making a call to
  // IAudioClient::SetEventHandle.
  if (use_event) {
    error = client->SetEventHandle(event_handle);
    if (FAILED(error.Error())) {
      RTC_LOG(LS_ERROR) << "IAudioClient::SetEventHandle failed: "
                        << ErrorToString(error);
      return error.Error();
    }
  }

  UINT32 buffer_size_in_frames = 0;
  // Retrieves the size (maximum capacity) of the endpoint buffer. The size is
  // expressed as the number of audio frames the buffer can hold.
  // For rendering clients, the buffer length determines the maximum amount of
  // rendering data that the application can write to the endpoint buffer
  // during a single processing pass. For capture clients, the buffer length
  // determines the maximum amount of capture data that the audio engine can
  // read from the endpoint buffer during a single processing pass.
  error = client->GetBufferSize(&buffer_size_in_frames);
  if (FAILED(error.Error())) {
    RTC_LOG(LS_ERROR) << "IAudioClient::GetBufferSize failed: "
                      << ErrorToString(error);
    return error.Error();
  }

  *endpoint_buffer_size = buffer_size_in_frames;
  RTC_DLOG(INFO) << "endpoint buffer size: " << buffer_size_in_frames
                 << " [audio frames]";
  const double size_in_ms = static_cast<double>(buffer_size_in_frames) /
                            (format->Format.nSamplesPerSec / 1000.0);
  RTC_DLOG(INFO) << "endpoint buffer size: "
                 << static_cast<int>(size_in_ms + 0.5) << " [ms]";
  RTC_DLOG(INFO) << "bytes per audio frame: " << format->Format.nBlockAlign;
  RTC_DLOG(INFO) << "endpoint buffer size: "
                 << buffer_size_in_frames * format->Format.nChannels *
                        (format->Format.wBitsPerSample / 8)
                 << " [bytes]";

  // TODO(henrika): utilize when delay measurements are added.
  REFERENCE_TIME latency = 0;
  error = client->GetStreamLatency(&latency);
  RTC_DLOG(INFO) << "stream latency: " << ReferenceTimeToTimeDelta(latency).ms()
                 << " [ms]";
  return error.Error();
}

HRESULT SharedModeInitializeLowLatency(IAudioClient3* client,
                                       const WAVEFORMATEXTENSIBLE* format,
                                       HANDLE event_handle,
                                       uint32_t period_in_frames,
                                       bool auto_convert_pcm,
                                       uint32_t* endpoint_buffer_size) {
  RTC_DLOG(INFO) << "SharedModeInitializeLowLatency: period_in_frames="
                 << period_in_frames
                 << ", auto_convert_pcm=" << auto_convert_pcm;
  RTC_DCHECK(client);
  RTC_DCHECK_GT(period_in_frames, 0);
  if (auto_convert_pcm) {
    RTC_DLOG(LS_WARNING) << "Sample rate converter is enabled";
  }

  // Define stream flags.
  DWORD stream_flags = AUDCLNT_STREAMFLAGS_NOPERSIST;
  bool use_event =
      (event_handle != nullptr && event_handle != INVALID_HANDLE_VALUE);
  if (use_event) {
    stream_flags |= AUDCLNT_STREAMFLAGS_EVENTCALLBACK;
    RTC_DLOG(INFO) << "The stream is initialized to be event driven";
  }
  if (auto_convert_pcm) {
    stream_flags |= AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM;
    stream_flags |= AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY;
  }
  RTC_DLOG(INFO) << "stream_flags: 0x" << rtc::ToHex(stream_flags);

  // Initialize the shared mode client for lowest possible latency.
  // It is assumed that GetSharedModeEnginePeriod() has been used to query the
  // smallest possible engine period and that it is given by |period_in_frames|.
  _com_error error = client->InitializeSharedAudioStream(
      stream_flags, period_in_frames,
      reinterpret_cast<const WAVEFORMATEX*>(format), nullptr);
  if (FAILED(error.Error())) {
    RTC_LOG(LS_ERROR) << "IAudioClient3::InitializeSharedAudioStream failed: "
                      << ErrorToString(error);
    return error.Error();
  }

  // Set the event handle.
  if (use_event) {
    error = client->SetEventHandle(event_handle);
    if (FAILED(error.Error())) {
      RTC_LOG(LS_ERROR) << "IAudioClient::SetEventHandle failed: "
                        << ErrorToString(error);
      return error.Error();
    }
  }

  UINT32 buffer_size_in_frames = 0;
  // Retrieve the size (maximum capacity) of the endpoint buffer.
  error = client->GetBufferSize(&buffer_size_in_frames);
  if (FAILED(error.Error())) {
    RTC_LOG(LS_ERROR) << "IAudioClient::GetBufferSize failed: "
                      << ErrorToString(error);
    return error.Error();
  }

  *endpoint_buffer_size = buffer_size_in_frames;
  RTC_DLOG(INFO) << "endpoint buffer size: " << buffer_size_in_frames
                 << " [audio frames]";
  const double size_in_ms = static_cast<double>(buffer_size_in_frames) /
                            (format->Format.nSamplesPerSec / 1000.0);
  RTC_DLOG(INFO) << "endpoint buffer size: "
                 << static_cast<int>(size_in_ms + 0.5) << " [ms]";
  RTC_DLOG(INFO) << "bytes per audio frame: " << format->Format.nBlockAlign;
  RTC_DLOG(INFO) << "endpoint buffer size: "
                 << buffer_size_in_frames * format->Format.nChannels *
                        (format->Format.wBitsPerSample / 8)
                 << " [bytes]";

  // TODO(henrika): utilize when delay measurements are added.
  REFERENCE_TIME latency = 0;
  error = client->GetStreamLatency(&latency);
  if (FAILED(error.Error())) {
    RTC_LOG(LS_WARNING) << "IAudioClient::GetStreamLatency failed: "
                        << ErrorToString(error);
  } else {
    RTC_DLOG(INFO) << "stream latency: "
                   << ReferenceTimeToTimeDelta(latency).ms() << " [ms]";
  }
  return error.Error();
}

ComPtr<IAudioRenderClient> CreateRenderClient(IAudioClient* client) {
  RTC_DLOG(INFO) << "CreateRenderClient";
  RTC_DCHECK(client);
  // Get access to the IAudioRenderClient interface. This interface
  // enables us to write output data to a rendering endpoint buffer.
  ComPtr<IAudioRenderClient> audio_render_client;
  _com_error error = client->GetService(IID_PPV_ARGS(&audio_render_client));
  if (FAILED(error.Error())) {
    RTC_LOG(LS_ERROR)
        << "IAudioClient::GetService(IID_IAudioRenderClient) failed: "
        << ErrorToString(error);
    return ComPtr<IAudioRenderClient>();
  }
  return audio_render_client;
}

ComPtr<IAudioCaptureClient> CreateCaptureClient(IAudioClient* client) {
  RTC_DLOG(INFO) << "CreateCaptureClient";
  RTC_DCHECK(client);
  // Get access to the IAudioCaptureClient interface. This interface
  // enables us to read input data from a capturing endpoint buffer.
  ComPtr<IAudioCaptureClient> audio_capture_client;
  _com_error error = client->GetService(IID_PPV_ARGS(&audio_capture_client));
  if (FAILED(error.Error())) {
    RTC_LOG(LS_ERROR)
        << "IAudioClient::GetService(IID_IAudioCaptureClient) failed: "
        << ErrorToString(error);
    return ComPtr<IAudioCaptureClient>();
  }
  return audio_capture_client;
}

ComPtr<IAudioClock> CreateAudioClock(IAudioClient* client) {
  RTC_DLOG(INFO) << "CreateAudioClock";
  RTC_DCHECK(client);
  // Get access to the IAudioClock interface. This interface enables us to
  // monitor a stream's data rate and the current position in the stream.
  ComPtr<IAudioClock> audio_clock;
  _com_error error = client->GetService(IID_PPV_ARGS(&audio_clock));
  if (FAILED(error.Error())) {
    RTC_LOG(LS_ERROR) << "IAudioClient::GetService(IID_IAudioClock) failed: "
                      << ErrorToString(error);
    return ComPtr<IAudioClock>();
  }
  return audio_clock;
}

ComPtr<IAudioSessionControl> CreateAudioSessionControl(IAudioClient* client) {
  RTC_DLOG(INFO) << "CreateAudioSessionControl";
  RTC_DCHECK(client);
  ComPtr<IAudioSessionControl> audio_session_control;
  _com_error error = client->GetService(IID_PPV_ARGS(&audio_session_control));
  if (FAILED(error.Error())) {
    RTC_LOG(LS_ERROR) << "IAudioClient::GetService(IID_IAudioControl) failed: "
                      << ErrorToString(error);
    return ComPtr<IAudioSessionControl>();
  }
  return audio_session_control;
}

ComPtr<ISimpleAudioVolume> CreateSimpleAudioVolume(IAudioClient* client) {
  RTC_DLOG(INFO) << "CreateSimpleAudioVolume";
  RTC_DCHECK(client);
  // Get access to the ISimpleAudioVolume interface. This interface enables a
  // client to control the master volume level of an audio session.
  ComPtr<ISimpleAudioVolume> simple_audio_volume;
  _com_error error = client->GetService(IID_PPV_ARGS(&simple_audio_volume));
  if (FAILED(error.Error())) {
    RTC_LOG(LS_ERROR)
        << "IAudioClient::GetService(IID_ISimpleAudioVolume) failed: "
        << ErrorToString(error);
    return ComPtr<ISimpleAudioVolume>();
  }
  return simple_audio_volume;
}

bool FillRenderEndpointBufferWithSilence(IAudioClient* client,
                                         IAudioRenderClient* render_client) {
  RTC_DLOG(INFO) << "FillRenderEndpointBufferWithSilence";
  RTC_DCHECK(client);
  RTC_DCHECK(render_client);
  UINT32 endpoint_buffer_size = 0;
  _com_error error = client->GetBufferSize(&endpoint_buffer_size);
  if (FAILED(error.Error())) {
    RTC_LOG(LS_ERROR) << "IAudioClient::GetBufferSize failed: "
                      << ErrorToString(error);
    return false;
  }

  UINT32 num_queued_frames = 0;
  // Get number of audio frames that are queued up to play in the endpoint
  // buffer.
  error = client->GetCurrentPadding(&num_queued_frames);
  if (FAILED(error.Error())) {
    RTC_LOG(LS_ERROR) << "IAudioClient::GetCurrentPadding failed: "
                      << ErrorToString(error);
    return false;
  }
  RTC_DLOG(INFO) << "num_queued_frames: " << num_queued_frames;

  BYTE* data = nullptr;
  int num_frames_to_fill = endpoint_buffer_size - num_queued_frames;
  RTC_DLOG(INFO) << "num_frames_to_fill: " << num_frames_to_fill;
  error = render_client->GetBuffer(num_frames_to_fill, &data);
  if (FAILED(error.Error())) {
    RTC_LOG(LS_ERROR) << "IAudioRenderClient::GetBuffer failed: "
                      << ErrorToString(error);
    return false;
  }

  // Using the AUDCLNT_BUFFERFLAGS_SILENT flag eliminates the need to
  // explicitly write silence data to the rendering buffer.
  error = render_client->ReleaseBuffer(num_frames_to_fill,
                                       AUDCLNT_BUFFERFLAGS_SILENT);
  if (FAILED(error.Error())) {
    RTC_LOG(LS_ERROR) << "IAudioRenderClient::ReleaseBuffer failed: "
                      << ErrorToString(error);
    return false;
  }

  return true;
}

std::string WaveFormatExToString(const WAVEFORMATEXTENSIBLE* format) {
  RTC_DCHECK_EQ(format->Format.wFormatTag, WAVE_FORMAT_EXTENSIBLE);
  char ss_buf[1024];
  rtc::SimpleStringBuilder ss(ss_buf);
  ss.AppendFormat("wFormatTag: WAVE_FORMAT_EXTENSIBLE");
  ss.AppendFormat(", nChannels: %d", format->Format.nChannels);
  ss.AppendFormat(", nSamplesPerSec: %d", format->Format.nSamplesPerSec);
  ss.AppendFormat(", nAvgBytesPerSec: %d", format->Format.nAvgBytesPerSec);
  ss.AppendFormat(", nBlockAlign: %d", format->Format.nBlockAlign);
  ss.AppendFormat(", wBitsPerSample: %d", format->Format.wBitsPerSample);
  ss.AppendFormat(", cbSize: %d", format->Format.cbSize);
  ss.AppendFormat(", wValidBitsPerSample: %d",
                  format->Samples.wValidBitsPerSample);
  ss.AppendFormat(", dwChannelMask: 0x%X", format->dwChannelMask);
  if (format->SubFormat == KSDATAFORMAT_SUBTYPE_PCM) {
    ss << ", SubFormat: KSDATAFORMAT_SUBTYPE_PCM";
  } else if (format->SubFormat == KSDATAFORMAT_SUBTYPE_IEEE_FLOAT) {
    ss << ", SubFormat: KSDATAFORMAT_SUBTYPE_IEEE_FLOAT";
  } else {
    ss << ", SubFormat: NOT_SUPPORTED";
  }
  ss.AppendFormat("\nChannel configuration: %s",
                  ChannelMaskToString(format->dwChannelMask).c_str());
  ss.AppendFormat("\nDirectSound configuration : %s",
                  DirectSoundConfigToString(format->dwChannelMask));
  return ss.str();
}

webrtc::TimeDelta ReferenceTimeToTimeDelta(REFERENCE_TIME time) {
  // Each unit of reference time is 100 nanoseconds <=> 0.1 microsecond.
  return webrtc::TimeDelta::us(0.1 * time + 0.5);
}

double FramesToMilliseconds(uint32_t num_frames, uint16_t sample_rate) {
  // Convert the current period in frames into milliseconds.
  return static_cast<double>(num_frames) / (sample_rate / 1000.0);
}

std::string ErrorToString(const _com_error& error) {
  char ss_buf[1024];
  rtc::SimpleStringBuilder ss(ss_buf);
  ss.AppendFormat("%s (0x%08X)", rtc::ToUtf8(error.ErrorMessage()).c_str(),
                  error.Error());
  return ss.str();
}

}  // namespace core_audio_utility
}  // namespace webrtc_win
}  // namespace webrtc
