| 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();
|
| }
|
| }
|
|
|
|
|