Index: media/audio/win/audio_manager_win.cc |
diff --git a/media/audio/win/audio_manager_win.cc b/media/audio/win/audio_manager_win.cc |
index 1d5538fa6ce5d7619fd5279a6bbfd67ba19283cf..02a04da780b89c7d181db9dd744795177fe6a781 100644 |
--- a/media/audio/win/audio_manager_win.cc |
+++ b/media/audio/win/audio_manager_win.cc |
@@ -281,6 +281,11 @@ AudioParameters AudioManagerWin::GetInputStreamParameters( |
sample_rate, 16, kFallbackBufferSize); |
} |
+std::string AudioManagerWin::GetAssociatedOutputDeviceID( |
+ const std::string& input_device_id) { |
+ return CoreAudioUtil::GetMatchingOutputDeviceID(input_device_id); |
+} |
+ |
// Factory for the implementations of AudioOutputStream for AUDIO_PCM_LINEAR |
// mode. |
// - PCMWaveOutAudioOutputStream: Based on the waveOut API. |
@@ -317,7 +322,7 @@ AudioOutputStream* AudioManagerWin::MakeLowLatencyOutputStream( |
this, params, media::NumberOfWaveOutBuffers(), WAVE_MAPPER); |
} |
- // TODO(crogers): support more than stereo input. |
+ // TODO(rtoy): support more than stereo input. |
if (params.input_channels() > 0) { |
DVLOG(1) << "WASAPIUnifiedStream is created."; |
return new WASAPIUnifiedStream(this, params, input_device_id); |
@@ -351,58 +356,69 @@ AudioInputStream* AudioManagerWin::MakeLowLatencyInputStream( |
return stream; |
} |
+std::string AudioManagerWin::GetDefaultOutputDeviceID() { |
+ if (!CoreAudioUtil::IsSupported()) |
+ return std::string(); |
+ return CoreAudioUtil::GetDefaultOutputDeviceID(); |
+} |
+ |
AudioParameters AudioManagerWin::GetPreferredOutputStreamParameters( |
const std::string& output_device_id, |
const AudioParameters& input_params) { |
// TODO(tommi): Support |output_device_id|. |
DLOG_IF(ERROR, !output_device_id.empty()) << "Not implemented!"; |
+ |
+ const bool core_audio_supported = CoreAudioUtil::IsSupported(); |
+ DLOG_IF(ERROR, !core_audio_supported && !output_device_id.empty()) |
+ << "CoreAudio is required to open non-default devices."; |
+ |
const CommandLine* cmd_line = CommandLine::ForCurrentProcess(); |
ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO; |
int sample_rate = 48000; |
int buffer_size = kFallbackBufferSize; |
int bits_per_sample = 16; |
int input_channels = 0; |
- bool use_input_params = !CoreAudioUtil::IsSupported(); |
- if (cmd_line->HasSwitch(switches::kEnableExclusiveAudio)) { |
- // TODO(crogers): tune these values for best possible WebAudio performance. |
- // WebRTC works well at 48kHz and a buffer size of 480 samples will be used |
- // for this case. Note that exclusive mode is experimental. |
- // This sample rate will be combined with a buffer size of 256 samples, |
- // which corresponds to an output delay of ~5.33ms. |
- sample_rate = 48000; |
- buffer_size = 256; |
- if (input_params.IsValid()) |
- channel_layout = input_params.channel_layout(); |
- } else if (!use_input_params) { |
- // Hardware sample-rate on Windows can be configured, so we must query. |
- // TODO(henrika): improve possibility to specify an audio endpoint. |
- // Use the default device (same as for Wave) for now to be compatible. |
- int hw_sample_rate = WASAPIAudioOutputStream::HardwareSampleRate(); |
- |
- AudioParameters params; |
- HRESULT hr = CoreAudioUtil::GetPreferredAudioParameters(eRender, eConsole, |
- ¶ms); |
- int hw_buffer_size = |
- FAILED(hr) ? kFallbackBufferSize : params.frames_per_buffer(); |
- channel_layout = WASAPIAudioOutputStream::HardwareChannelLayout(); |
- |
- // TODO(henrika): Figure out the right thing to do here. |
- if (hw_sample_rate && hw_buffer_size) { |
- sample_rate = hw_sample_rate; |
- buffer_size = hw_buffer_size; |
+ bool use_input_params = !core_audio_supported; |
+ if (core_audio_supported) { |
+ if (cmd_line->HasSwitch(switches::kEnableExclusiveAudio)) { |
+ // TODO(rtoy): tune these values for best possible WebAudio |
+ // performance. WebRTC works well at 48kHz and a buffer size of 480 |
+ // samples will be used for this case. Note that exclusive mode is |
+ // experimental. This sample rate will be combined with a buffer size of |
+ // 256 samples, which corresponds to an output delay of ~5.33ms. |
+ sample_rate = 48000; |
+ buffer_size = 256; |
+ if (input_params.IsValid()) |
+ channel_layout = input_params.channel_layout(); |
} else { |
- use_input_params = true; |
+ AudioParameters params; |
+ HRESULT hr = CoreAudioUtil::GetPreferredAudioParameters(output_device_id, |
+ ¶ms); |
+ if (SUCCEEDED(hr)) { |
+ bits_per_sample = params.bits_per_sample(); |
+ buffer_size = params.frames_per_buffer(); |
+ channel_layout = params.channel_layout(); |
+ sample_rate = params.sample_rate(); |
+ } else { |
+ use_input_params = true; |
+ } |
} |
} |
if (input_params.IsValid()) { |
- if (cmd_line->HasSwitch(switches::kTrySupportedChannelLayouts) && |
- CoreAudioUtil::IsSupported()) { |
+ if (core_audio_supported && |
+ cmd_line->HasSwitch(switches::kTrySupportedChannelLayouts)) { |
// Check if it is possible to open up at the specified input channel |
// layout but avoid checking if the specified layout is the same as the |
// hardware (preferred) layout. We do this extra check to avoid the |
// CoreAudioUtil::IsChannelLayoutSupported() overhead in most cases. |
if (input_params.channel_layout() != channel_layout) { |
+ // TODO(henrika): Use |output_device_id| here. |
+ // Internally, IsChannelLayoutSupported does many of the operations |
+ // that have already been done such as opening up a client and fetching |
+ // the WAVEFORMATPCMEX format. Ideally we should only do that once and |
+ // do it for the requested device. Then here, we can check the layout |
+ // from the data we already hold. |
if (CoreAudioUtil::IsChannelLayoutSupported( |
eRender, eConsole, input_params.channel_layout())) { |
// Open up using the same channel layout as the source if it is |
@@ -420,10 +436,10 @@ AudioParameters AudioManagerWin::GetPreferredOutputStreamParameters( |
// equal to the input values, AudioOutputResampler will skip resampling |
// and bit per sample differences (since the input parameters will match |
// the output parameters). |
- sample_rate = input_params.sample_rate(); |
bits_per_sample = input_params.bits_per_sample(); |
- channel_layout = input_params.channel_layout(); |
buffer_size = input_params.frames_per_buffer(); |
+ channel_layout = input_params.channel_layout(); |
+ sample_rate = input_params.sample_rate(); |
} |
} |