Home | History | Annotate | Download | only in win
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "media/audio/audio_io.h"
      6 
      7 #include <windows.h>
      8 #include <objbase.h>  // This has to be before initguid.h
      9 #include <initguid.h>
     10 #include <mmsystem.h>
     11 #include <setupapi.h>
     12 
     13 #include "base/bind.h"
     14 #include "base/bind_helpers.h"
     15 #include "base/command_line.h"
     16 #include "base/files/file_path.h"
     17 #include "base/memory/scoped_ptr.h"
     18 #include "base/message_loop/message_loop.h"
     19 #include "base/path_service.h"
     20 #include "base/process/launch.h"
     21 #include "base/strings/string_number_conversions.h"
     22 #include "base/strings/string_util.h"
     23 #include "base/win/windows_version.h"
     24 #include "media/audio/audio_parameters.h"
     25 #include "media/audio/win/audio_device_listener_win.h"
     26 #include "media/audio/win/audio_low_latency_input_win.h"
     27 #include "media/audio/win/audio_low_latency_output_win.h"
     28 #include "media/audio/win/audio_manager_win.h"
     29 #include "media/audio/win/audio_unified_win.h"
     30 #include "media/audio/win/core_audio_util_win.h"
     31 #include "media/audio/win/device_enumeration_win.h"
     32 #include "media/audio/win/wavein_input_win.h"
     33 #include "media/audio/win/waveout_output_win.h"
     34 #include "media/base/bind_to_loop.h"
     35 #include "media/base/channel_layout.h"
     36 #include "media/base/limits.h"
     37 #include "media/base/media_switches.h"
     38 
     39 // Libraries required for the SetupAPI and Wbem APIs used here.
     40 #pragma comment(lib, "setupapi.lib")
     41 
     42 // The following are defined in various DDK headers, and we (re)define them here
     43 // to avoid adding the DDK as a chrome dependency.
     44 #define DRV_QUERYDEVICEINTERFACE 0x80c
     45 #define DRVM_MAPPER_PREFERRED_GET 0x2015
     46 #define DRV_QUERYDEVICEINTERFACESIZE 0x80d
     47 DEFINE_GUID(AM_KSCATEGORY_AUDIO, 0x6994ad04, 0x93ef, 0x11d0,
     48             0xa3, 0xcc, 0x00, 0xa0, 0xc9, 0x22, 0x31, 0x96);
     49 
     50 namespace media {
     51 
     52 // Maximum number of output streams that can be open simultaneously.
     53 static const int kMaxOutputStreams = 50;
     54 
     55 // Up to 8 channels can be passed to the driver.  This should work, given the
     56 // right drivers, but graceful error handling is needed.
     57 static const int kWinMaxChannels = 8;
     58 
     59 // We use 3 buffers for recording audio so that if a recording callback takes
     60 // some time to return we won't lose audio. More buffers while recording are
     61 // ok because they don't introduce any delay in recording, unlike in playback
     62 // where you first need to fill in that number of buffers before starting to
     63 // play.
     64 static const int kNumInputBuffers = 3;
     65 
     66 // Buffer size to use for input and output stream when a proper size can't be
     67 // determined from the system
     68 static const int kFallbackBufferSize = 2048;
     69 
     70 static int GetVersionPartAsInt(DWORDLONG num) {
     71   return static_cast<int>(num & 0xffff);
     72 }
     73 
     74 // Returns a string containing the given device's description and installed
     75 // driver version.
     76 static base::string16 GetDeviceAndDriverInfo(HDEVINFO device_info,
     77                                              SP_DEVINFO_DATA* device_data) {
     78   // Save the old install params setting and set a flag for the
     79   // SetupDiBuildDriverInfoList below to return only the installed drivers.
     80   SP_DEVINSTALL_PARAMS old_device_install_params;
     81   old_device_install_params.cbSize = sizeof(old_device_install_params);
     82   SetupDiGetDeviceInstallParams(device_info, device_data,
     83                                 &old_device_install_params);
     84   SP_DEVINSTALL_PARAMS device_install_params = old_device_install_params;
     85   device_install_params.FlagsEx |= DI_FLAGSEX_INSTALLEDDRIVER;
     86   SetupDiSetDeviceInstallParams(device_info, device_data,
     87                                 &device_install_params);
     88 
     89   SP_DRVINFO_DATA driver_data;
     90   driver_data.cbSize = sizeof(driver_data);
     91   base::string16 device_and_driver_info;
     92   if (SetupDiBuildDriverInfoList(device_info, device_data,
     93                                  SPDIT_COMPATDRIVER)) {
     94     if (SetupDiEnumDriverInfo(device_info, device_data, SPDIT_COMPATDRIVER, 0,
     95                               &driver_data)) {
     96       DWORDLONG version = driver_data.DriverVersion;
     97       device_and_driver_info = base::string16(driver_data.Description) + L" v" +
     98           base::IntToString16(GetVersionPartAsInt((version >> 48))) + L"." +
     99           base::IntToString16(GetVersionPartAsInt((version >> 32))) + L"." +
    100           base::IntToString16(GetVersionPartAsInt((version >> 16))) + L"." +
    101           base::IntToString16(GetVersionPartAsInt(version));
    102     }
    103     SetupDiDestroyDriverInfoList(device_info, device_data, SPDIT_COMPATDRIVER);
    104   }
    105 
    106   SetupDiSetDeviceInstallParams(device_info, device_data,
    107                                 &old_device_install_params);
    108 
    109   return device_and_driver_info;
    110 }
    111 
    112 static int NumberOfWaveOutBuffers() {
    113   // Use the user provided buffer count if provided.
    114   int buffers = 0;
    115   std::string buffers_str(CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
    116       switches::kWaveOutBuffers));
    117   if (base::StringToInt(buffers_str, &buffers) && buffers > 0) {
    118     return buffers;
    119   }
    120 
    121   // Use 4 buffers for Vista, 3 for everyone else:
    122   //  - The entire Windows audio stack was rewritten for Windows Vista and wave
    123   //    out performance was degraded compared to XP.
    124   //  - The regression was fixed in Windows 7 and most configurations will work
    125   //    with 2, but some (e.g., some Sound Blasters) still need 3.
    126   //  - Some XP configurations (even multi-processor ones) also need 3.
    127   return (base::win::GetVersion() == base::win::VERSION_VISTA) ? 4 : 3;
    128 }
    129 
    130 AudioManagerWin::AudioManagerWin(AudioLogFactory* audio_log_factory)
    131     : AudioManagerBase(audio_log_factory) {
    132   if (!CoreAudioUtil::IsSupported()) {
    133     // Use the Wave API for device enumeration if XP or lower.
    134     enumeration_type_ = kWaveEnumeration;
    135   } else {
    136     // Use the MMDevice API for device enumeration if Vista or higher.
    137     enumeration_type_ = kMMDeviceEnumeration;
    138   }
    139 
    140   SetMaxOutputStreamsAllowed(kMaxOutputStreams);
    141 
    142   // Task must be posted last to avoid races from handing out "this" to the
    143   // audio thread.
    144   GetMessageLoop()->PostTask(FROM_HERE, base::Bind(
    145       &AudioManagerWin::CreateDeviceListener, base::Unretained(this)));
    146 }
    147 
    148 AudioManagerWin::~AudioManagerWin() {
    149   // It's safe to post a task here since Shutdown() will wait for all tasks to
    150   // complete before returning.
    151   GetMessageLoop()->PostTask(FROM_HERE, base::Bind(
    152       &AudioManagerWin::DestroyDeviceListener, base::Unretained(this)));
    153   Shutdown();
    154 }
    155 
    156 bool AudioManagerWin::HasAudioOutputDevices() {
    157   return (::waveOutGetNumDevs() != 0);
    158 }
    159 
    160 bool AudioManagerWin::HasAudioInputDevices() {
    161   return (::waveInGetNumDevs() != 0);
    162 }
    163 
    164 void AudioManagerWin::CreateDeviceListener() {
    165   // AudioDeviceListenerWin must be initialized on a COM thread and should only
    166   // be used if WASAPI / Core Audio is supported.
    167   if (CoreAudioUtil::IsSupported()) {
    168     output_device_listener_.reset(new AudioDeviceListenerWin(BindToLoop(
    169         GetMessageLoop(), base::Bind(
    170             &AudioManagerWin::NotifyAllOutputDeviceChangeListeners,
    171             base::Unretained(this)))));
    172   }
    173 }
    174 
    175 void AudioManagerWin::DestroyDeviceListener() {
    176   output_device_listener_.reset();
    177 }
    178 
    179 base::string16 AudioManagerWin::GetAudioInputDeviceModel() {
    180   // Get the default audio capture device and its device interface name.
    181   DWORD device_id = 0;
    182   waveInMessage(reinterpret_cast<HWAVEIN>(WAVE_MAPPER),
    183                 DRVM_MAPPER_PREFERRED_GET,
    184                 reinterpret_cast<DWORD_PTR>(&device_id), NULL);
    185   ULONG device_interface_name_size = 0;
    186   waveInMessage(reinterpret_cast<HWAVEIN>(device_id),
    187                 DRV_QUERYDEVICEINTERFACESIZE,
    188                 reinterpret_cast<DWORD_PTR>(&device_interface_name_size), 0);
    189   size_t bytes_in_char16 = sizeof(base::string16::value_type);
    190   DCHECK_EQ(0u, device_interface_name_size % bytes_in_char16);
    191   if (device_interface_name_size <= bytes_in_char16)
    192     return base::string16();  // No audio capture device.
    193 
    194   base::string16 device_interface_name;
    195   base::string16::value_type* name_ptr = WriteInto(&device_interface_name,
    196       device_interface_name_size / bytes_in_char16);
    197   waveInMessage(reinterpret_cast<HWAVEIN>(device_id),
    198                 DRV_QUERYDEVICEINTERFACE,
    199                 reinterpret_cast<DWORD_PTR>(name_ptr),
    200                 static_cast<DWORD_PTR>(device_interface_name_size));
    201 
    202   // Enumerate all audio devices and find the one matching the above device
    203   // interface name.
    204   HDEVINFO device_info = SetupDiGetClassDevs(
    205       &AM_KSCATEGORY_AUDIO, 0, 0, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
    206   if (device_info == INVALID_HANDLE_VALUE)
    207     return base::string16();
    208 
    209   DWORD interface_index = 0;
    210   SP_DEVICE_INTERFACE_DATA interface_data;
    211   interface_data.cbSize = sizeof(interface_data);
    212   while (SetupDiEnumDeviceInterfaces(device_info, 0, &AM_KSCATEGORY_AUDIO,
    213                                      interface_index++, &interface_data)) {
    214     // Query the size of the struct, allocate it and then query the data.
    215     SP_DEVINFO_DATA device_data;
    216     device_data.cbSize = sizeof(device_data);
    217     DWORD interface_detail_size = 0;
    218     SetupDiGetDeviceInterfaceDetail(device_info, &interface_data, 0, 0,
    219                                     &interface_detail_size, &device_data);
    220     if (!interface_detail_size)
    221       continue;
    222 
    223     scoped_ptr<char[]> interface_detail_buffer(new char[interface_detail_size]);
    224     SP_DEVICE_INTERFACE_DETAIL_DATA* interface_detail =
    225         reinterpret_cast<SP_DEVICE_INTERFACE_DETAIL_DATA*>(
    226             interface_detail_buffer.get());
    227     interface_detail->cbSize = interface_detail_size;
    228     if (!SetupDiGetDeviceInterfaceDetail(device_info, &interface_data,
    229                                          interface_detail,
    230                                          interface_detail_size, NULL,
    231                                          &device_data))
    232       return base::string16();
    233 
    234     bool device_found = (device_interface_name == interface_detail->DevicePath);
    235 
    236     if (device_found)
    237       return GetDeviceAndDriverInfo(device_info, &device_data);
    238   }
    239 
    240   return base::string16();
    241 }
    242 
    243 void AudioManagerWin::ShowAudioInputSettings() {
    244   std::wstring program;
    245   std::string argument;
    246   if (!CoreAudioUtil::IsSupported()) {
    247     program = L"sndvol32.exe";
    248     argument = "-R";
    249   } else {
    250     program = L"control.exe";
    251     argument = "mmsys.cpl,,1";
    252   }
    253 
    254   base::FilePath path;
    255   PathService::Get(base::DIR_SYSTEM, &path);
    256   path = path.Append(program);
    257   CommandLine command_line(path);
    258   command_line.AppendArg(argument);
    259   base::LaunchProcess(command_line, base::LaunchOptions(), NULL);
    260 }
    261 
    262 void AudioManagerWin::GetAudioDeviceNamesImpl(
    263     bool input,
    264     AudioDeviceNames* device_names) {
    265   DCHECK(device_names->empty());
    266   DCHECK(enumeration_type() !=  kUninitializedEnumeration);
    267   // Enumerate all active audio-endpoint capture devices.
    268   if (enumeration_type() == kWaveEnumeration) {
    269     // Utilize the Wave API for Windows XP.
    270     if (input)
    271       GetInputDeviceNamesWinXP(device_names);
    272     else
    273       GetOutputDeviceNamesWinXP(device_names);
    274   } else {
    275     // Utilize the MMDevice API (part of Core Audio) for Vista and higher.
    276     if (input)
    277       GetInputDeviceNamesWin(device_names);
    278     else
    279       GetOutputDeviceNamesWin(device_names);
    280   }
    281 
    282   // Always add default device parameters as first element.
    283   if (!device_names->empty()) {
    284     AudioDeviceName name;
    285     name.device_name = AudioManagerBase::kDefaultDeviceName;
    286     name.unique_id = AudioManagerBase::kDefaultDeviceId;
    287     device_names->push_front(name);
    288   }
    289 }
    290 
    291 void AudioManagerWin::GetAudioInputDeviceNames(AudioDeviceNames* device_names) {
    292   GetAudioDeviceNamesImpl(true, device_names);
    293 }
    294 
    295 void AudioManagerWin::GetAudioOutputDeviceNames(
    296     AudioDeviceNames* device_names) {
    297   GetAudioDeviceNamesImpl(false, device_names);
    298 }
    299 
    300 AudioParameters AudioManagerWin::GetInputStreamParameters(
    301     const std::string& device_id) {
    302   int sample_rate = 48000;
    303   ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO;
    304   if (CoreAudioUtil::IsSupported()) {
    305     int hw_sample_rate = WASAPIAudioInputStream::HardwareSampleRate(device_id);
    306     if (hw_sample_rate)
    307       sample_rate = hw_sample_rate;
    308     channel_layout =
    309         WASAPIAudioInputStream::HardwareChannelCount(device_id) == 1 ?
    310             CHANNEL_LAYOUT_MONO : CHANNEL_LAYOUT_STEREO;
    311   }
    312 
    313   // TODO(Henrika): improve the default buffer size value for input stream.
    314   return AudioParameters(
    315       AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout,
    316       sample_rate, 16, kFallbackBufferSize);
    317 }
    318 
    319 std::string AudioManagerWin::GetAssociatedOutputDeviceID(
    320     const std::string& input_device_id) {
    321   if (!CoreAudioUtil::IsSupported()) {
    322     NOTIMPLEMENTED()
    323         << "GetAssociatedOutputDeviceID is not supported on this OS";
    324     return std::string();
    325   }
    326   return CoreAudioUtil::GetMatchingOutputDeviceID(input_device_id);
    327 }
    328 
    329 // Factory for the implementations of AudioOutputStream for AUDIO_PCM_LINEAR
    330 // mode.
    331 // - PCMWaveOutAudioOutputStream: Based on the waveOut API.
    332 AudioOutputStream* AudioManagerWin::MakeLinearOutputStream(
    333     const AudioParameters& params) {
    334   DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
    335   if (params.channels() > kWinMaxChannels)
    336     return NULL;
    337 
    338   return new PCMWaveOutAudioOutputStream(this,
    339                                          params,
    340                                          NumberOfWaveOutBuffers(),
    341                                          WAVE_MAPPER);
    342 }
    343 
    344 // Factory for the implementations of AudioOutputStream for
    345 // AUDIO_PCM_LOW_LATENCY mode. Two implementations should suffice most
    346 // windows user's needs.
    347 // - PCMWaveOutAudioOutputStream: Based on the waveOut API.
    348 // - WASAPIAudioOutputStream: Based on Core Audio (WASAPI) API.
    349 AudioOutputStream* AudioManagerWin::MakeLowLatencyOutputStream(
    350     const AudioParameters& params,
    351     const std::string& device_id,
    352     const std::string& input_device_id) {
    353   DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
    354   if (params.channels() > kWinMaxChannels)
    355     return NULL;
    356 
    357   if (!CoreAudioUtil::IsSupported()) {
    358     // Fall back to Windows Wave implementation on Windows XP or lower.
    359     DLOG_IF(ERROR, !device_id.empty() &&
    360         device_id != AudioManagerBase::kDefaultDeviceId)
    361         << "Opening by device id not supported by PCMWaveOutAudioOutputStream";
    362     DVLOG(1) << "Using WaveOut since WASAPI requires at least Vista.";
    363     return new PCMWaveOutAudioOutputStream(
    364         this, params, NumberOfWaveOutBuffers(), WAVE_MAPPER);
    365   }
    366 
    367   // TODO(rtoy): support more than stereo input.
    368   if (params.input_channels() > 0) {
    369     DVLOG(1) << "WASAPIUnifiedStream is created.";
    370     DLOG_IF(ERROR, !device_id.empty() &&
    371         device_id != AudioManagerBase::kDefaultDeviceId)
    372         << "Opening by device id not supported by WASAPIUnifiedStream";
    373     return new WASAPIUnifiedStream(this, params, input_device_id);
    374   }
    375 
    376   // Pass an empty string to indicate that we want the default device
    377   // since we consistently only check for an empty string in
    378   // WASAPIAudioOutputStream.
    379   return new WASAPIAudioOutputStream(this,
    380       device_id == AudioManagerBase::kDefaultDeviceId ?
    381           std::string() : device_id,
    382       params, eConsole);
    383 }
    384 
    385 // Factory for the implementations of AudioInputStream for AUDIO_PCM_LINEAR
    386 // mode.
    387 AudioInputStream* AudioManagerWin::MakeLinearInputStream(
    388     const AudioParameters& params, const std::string& device_id) {
    389   DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
    390   return CreatePCMWaveInAudioInputStream(params, device_id);
    391 }
    392 
    393 // Factory for the implementations of AudioInputStream for
    394 // AUDIO_PCM_LOW_LATENCY mode.
    395 AudioInputStream* AudioManagerWin::MakeLowLatencyInputStream(
    396     const AudioParameters& params, const std::string& device_id) {
    397   DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
    398   AudioInputStream* stream = NULL;
    399   if (!CoreAudioUtil::IsSupported()) {
    400     // Fall back to Windows Wave implementation on Windows XP or lower.
    401     DVLOG(1) << "Using WaveIn since WASAPI requires at least Vista.";
    402     stream = CreatePCMWaveInAudioInputStream(params, device_id);
    403   } else {
    404     stream = new WASAPIAudioInputStream(this, params, device_id);
    405   }
    406 
    407   return stream;
    408 }
    409 
    410 std::string AudioManagerWin::GetDefaultOutputDeviceID() {
    411   if (!CoreAudioUtil::IsSupported())
    412     return std::string();
    413   return CoreAudioUtil::GetDefaultOutputDeviceID();
    414 }
    415 
    416 AudioParameters AudioManagerWin::GetPreferredOutputStreamParameters(
    417     const std::string& output_device_id,
    418     const AudioParameters& input_params) {
    419   const bool core_audio_supported = CoreAudioUtil::IsSupported();
    420   DLOG_IF(ERROR, !core_audio_supported && !output_device_id.empty())
    421       << "CoreAudio is required to open non-default devices.";
    422 
    423   const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
    424   ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO;
    425   int sample_rate = 48000;
    426   int buffer_size = kFallbackBufferSize;
    427   int bits_per_sample = 16;
    428   int input_channels = 0;
    429   bool use_input_params = !core_audio_supported;
    430   if (core_audio_supported) {
    431     if (cmd_line->HasSwitch(switches::kEnableExclusiveAudio)) {
    432       // TODO(rtoy): tune these values for best possible WebAudio
    433       // performance. WebRTC works well at 48kHz and a buffer size of 480
    434       // samples will be used for this case. Note that exclusive mode is
    435       // experimental. This sample rate will be combined with a buffer size of
    436       // 256 samples, which corresponds to an output delay of ~5.33ms.
    437       sample_rate = 48000;
    438       buffer_size = 256;
    439       if (input_params.IsValid())
    440         channel_layout = input_params.channel_layout();
    441     } else {
    442       AudioParameters params;
    443       HRESULT hr = CoreAudioUtil::GetPreferredAudioParameters(
    444           output_device_id.empty() ?
    445               GetDefaultOutputDeviceID() : output_device_id,
    446           &params);
    447       if (SUCCEEDED(hr)) {
    448         bits_per_sample = params.bits_per_sample();
    449         buffer_size = params.frames_per_buffer();
    450         channel_layout = params.channel_layout();
    451         sample_rate = params.sample_rate();
    452       } else {
    453         use_input_params = true;
    454       }
    455     }
    456   }
    457 
    458   if (input_params.IsValid()) {
    459     // If the user has enabled checking supported channel layouts or we don't
    460     // have a valid channel layout yet, try to use the input layout.  See bugs
    461     // http://crbug.com/259165 and http://crbug.com/311906 for more details.
    462     if (core_audio_supported &&
    463         (cmd_line->HasSwitch(switches::kTrySupportedChannelLayouts) ||
    464          channel_layout == CHANNEL_LAYOUT_UNSUPPORTED)) {
    465       // Check if it is possible to open up at the specified input channel
    466       // layout but avoid checking if the specified layout is the same as the
    467       // hardware (preferred) layout. We do this extra check to avoid the
    468       // CoreAudioUtil::IsChannelLayoutSupported() overhead in most cases.
    469       if (input_params.channel_layout() != channel_layout) {
    470         // TODO(henrika): Internally, IsChannelLayoutSupported does many of the
    471         // operations that have already been done such as opening up a client
    472         // and fetching the WAVEFORMATPCMEX format.  Ideally we should only do
    473         // that once.  Then here, we can check the layout from the data we
    474         // already hold.
    475         if (CoreAudioUtil::IsChannelLayoutSupported(
    476                 output_device_id, eRender, eConsole,
    477                 input_params.channel_layout())) {
    478           // Open up using the same channel layout as the source if it is
    479           // supported by the hardware.
    480           channel_layout = input_params.channel_layout();
    481           VLOG(1) << "Hardware channel layout is not used; using same layout"
    482                   << " as the source instead (" << channel_layout << ")";
    483         }
    484       }
    485     }
    486     input_channels = input_params.input_channels();
    487     if (use_input_params) {
    488       // If WASAPI isn't supported we'll fallback to WaveOut, which will take
    489       // care of resampling and bits per sample changes.  By setting these
    490       // equal to the input values, AudioOutputResampler will skip resampling
    491       // and bit per sample differences (since the input parameters will match
    492       // the output parameters).
    493       bits_per_sample = input_params.bits_per_sample();
    494       buffer_size = input_params.frames_per_buffer();
    495       channel_layout = input_params.channel_layout();
    496       sample_rate = input_params.sample_rate();
    497     }
    498   }
    499 
    500   int user_buffer_size = GetUserBufferSize();
    501   if (user_buffer_size)
    502     buffer_size = user_buffer_size;
    503 
    504   return AudioParameters(
    505       AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, input_channels,
    506       sample_rate, bits_per_sample, buffer_size, AudioParameters::NO_EFFECTS);
    507 }
    508 
    509 AudioInputStream* AudioManagerWin::CreatePCMWaveInAudioInputStream(
    510     const AudioParameters& params,
    511     const std::string& device_id) {
    512   std::string xp_device_id = device_id;
    513   if (device_id != AudioManagerBase::kDefaultDeviceId &&
    514       enumeration_type_ == kMMDeviceEnumeration) {
    515     xp_device_id = ConvertToWinXPInputDeviceId(device_id);
    516     if (xp_device_id.empty()) {
    517       DLOG(ERROR) << "Cannot find a waveIn device which matches the device ID "
    518                   << device_id;
    519       return NULL;
    520     }
    521   }
    522 
    523   return new PCMWaveInAudioInputStream(this, params, kNumInputBuffers,
    524                                        xp_device_id);
    525 }
    526 
    527 /// static
    528 AudioManager* CreateAudioManager(AudioLogFactory* audio_log_factory) {
    529   return new AudioManagerWin(audio_log_factory);
    530 }
    531 
    532 }  // namespace media
    533