diff options
Diffstat (limited to 'media/audio')
-rw-r--r-- | media/audio/win/audio_low_latency_output_win.cc | 66 | ||||
-rw-r--r-- | media/audio/win/audio_low_latency_output_win.h | 11 | ||||
-rw-r--r-- | media/audio/win/audio_manager_win.cc | 28 | ||||
-rw-r--r-- | media/audio/win/audio_unified_win.cc | 22 | ||||
-rw-r--r-- | media/audio/win/core_audio_util_win.cc | 48 | ||||
-rw-r--r-- | media/audio/win/core_audio_util_win.h | 38 | ||||
-rw-r--r-- | media/audio/win/core_audio_util_win_unittest.cc | 4 |
7 files changed, 83 insertions, 134 deletions
diff --git a/media/audio/win/audio_low_latency_output_win.cc b/media/audio/win/audio_low_latency_output_win.cc index c5402fa..8ba8821 100644 --- a/media/audio/win/audio_low_latency_output_win.cc +++ b/media/audio/win/audio_low_latency_output_win.cc @@ -25,23 +25,6 @@ using base::win::ScopedCoMem; namespace media { -typedef uint32 ChannelConfig; - -// Retrieves an integer mask which corresponds to the channel layout the -// audio engine uses for its internal processing/mixing of shared-mode -// streams. This mask indicates which channels are present in the multi- -// channel stream. The least significant bit corresponds with the Front Left -// speaker, the next least significant bit corresponds to the Front Right -// speaker, and so on, continuing in the order defined in KsMedia.h. -// See http://msdn.microsoft.com/en-us/library/windows/hardware/ff537083(v=vs.85).aspx -// for more details. -static ChannelConfig GetChannelConfig() { - WAVEFORMATPCMEX format; - return SUCCEEDED(CoreAudioUtil::GetDefaultSharedModeMixFormat( - eRender, eConsole, &format)) ? - static_cast<int>(format.dwChannelMask) : 0; -} - // Compare two sets of audio parameters and return true if they are equal. // Note that bits_per_sample() is excluded from this comparison since Core // Audio can deal with most bit depths. As an example, if the native/mixing @@ -55,40 +38,6 @@ static bool CompareAudioParametersNoBitDepthOrChannels( a.frames_per_buffer() == b.frames_per_buffer()); } -// Converts Microsoft's channel configuration to ChannelLayout. -// This mapping is not perfect but the best we can do given the current -// ChannelLayout enumerator and the Windows-specific speaker configurations -// defined in ksmedia.h. Don't assume that the channel ordering in -// ChannelLayout is exactly the same as the Windows specific configuration. -// As an example: KSAUDIO_SPEAKER_7POINT1_SURROUND is mapped to -// CHANNEL_LAYOUT_7_1 but the positions of Back L, Back R and Side L, Side R -// speakers are different in these two definitions. -static ChannelLayout ChannelConfigToChannelLayout(ChannelConfig config) { - switch (config) { - case KSAUDIO_SPEAKER_DIRECTOUT: - return CHANNEL_LAYOUT_NONE; - case KSAUDIO_SPEAKER_MONO: - return CHANNEL_LAYOUT_MONO; - case KSAUDIO_SPEAKER_STEREO: - return CHANNEL_LAYOUT_STEREO; - case KSAUDIO_SPEAKER_QUAD: - return CHANNEL_LAYOUT_QUAD; - case KSAUDIO_SPEAKER_SURROUND: - return CHANNEL_LAYOUT_4_0; - case KSAUDIO_SPEAKER_5POINT1: - return CHANNEL_LAYOUT_5_1_BACK; - case KSAUDIO_SPEAKER_5POINT1_SURROUND: - return CHANNEL_LAYOUT_5_1; - case KSAUDIO_SPEAKER_7POINT1: - return CHANNEL_LAYOUT_7_1_WIDE; - case KSAUDIO_SPEAKER_7POINT1_SURROUND: - return CHANNEL_LAYOUT_7_1; - default: - VLOG(1) << "Unsupported channel layout: " << config; - return CHANNEL_LAYOUT_UNSUPPORTED; - } -} - // static AUDCLNT_SHAREMODE WASAPIAudioOutputStream::GetShareMode() { const CommandLine* cmd_line = CommandLine::ForCurrentProcess(); @@ -98,19 +47,6 @@ AUDCLNT_SHAREMODE WASAPIAudioOutputStream::GetShareMode() { } // static -int WASAPIAudioOutputStream::HardwareChannelCount() { - WAVEFORMATPCMEX format; - return SUCCEEDED(CoreAudioUtil::GetDefaultSharedModeMixFormat( - eRender, eConsole, &format)) ? - static_cast<int>(format.Format.nChannels) : 0; -} - -// static -ChannelLayout WASAPIAudioOutputStream::HardwareChannelLayout() { - return ChannelConfigToChannelLayout(GetChannelConfig()); -} - -// static int WASAPIAudioOutputStream::HardwareSampleRate(const std::string& device_id) { WAVEFORMATPCMEX format; ScopedComPtr<IAudioClient> client; @@ -187,7 +123,7 @@ WASAPIAudioOutputStream::WASAPIAudioOutputStream(AudioManagerWin* manager, // Add the parts which are unique to WAVE_FORMAT_EXTENSIBLE. format_.Samples.wValidBitsPerSample = params.bits_per_sample(); - format_.dwChannelMask = GetChannelConfig(); + format_.dwChannelMask = CoreAudioUtil::GetChannelConfig(device_id, eRender); format_.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; // Store size (in different units) of audio packets which we expect to diff --git a/media/audio/win/audio_low_latency_output_win.h b/media/audio/win/audio_low_latency_output_win.h index 51e7dee..4efc0f6 100644 --- a/media/audio/win/audio_low_latency_output_win.h +++ b/media/audio/win/audio_low_latency_output_win.h @@ -138,17 +138,6 @@ class MEDIA_EXPORT WASAPIAudioOutputStream : virtual void SetVolume(double volume) OVERRIDE; virtual void GetVolume(double* volume) OVERRIDE; - // Retrieves the number of channels the audio engine uses for its internal - // processing/mixing of shared-mode streams for the default endpoint device. - static int HardwareChannelCount(); - - // Retrieves the channel layout the audio engine uses for its internal - // processing/mixing of shared-mode streams for the default endpoint device. - // Note that we convert an internal channel layout mask (see ChannelMask()) - // into a Chrome-specific channel layout enumerator in this method, hence - // the match might not be perfect. - static ChannelLayout HardwareChannelLayout(); - // Retrieves the sample rate the audio engine uses for its internal // processing/mixing of shared-mode streams. To fetch the settings for the // default device, pass an empty string as the |device_id|. diff --git a/media/audio/win/audio_manager_win.cc b/media/audio/win/audio_manager_win.cc index 71d9dd8..254fe36 100644 --- a/media/audio/win/audio_manager_win.cc +++ b/media/audio/win/audio_manager_win.cc @@ -355,7 +355,8 @@ AudioOutputStream* AudioManagerWin::MakeLowLatencyOutputStream( if (!CoreAudioUtil::IsSupported()) { // Fall back to Windows Wave implementation on Windows XP or lower. - DLOG_IF(ERROR, !device_id.empty()) + DLOG_IF(ERROR, !device_id.empty() && + device_id != AudioManagerBase::kDefaultDeviceId) << "Opening by device id not supported by PCMWaveOutAudioOutputStream"; DVLOG(1) << "Using WaveOut since WASAPI requires at least Vista."; return new PCMWaveOutAudioOutputStream( @@ -365,12 +366,19 @@ AudioOutputStream* AudioManagerWin::MakeLowLatencyOutputStream( // TODO(rtoy): support more than stereo input. if (params.input_channels() > 0) { DVLOG(1) << "WASAPIUnifiedStream is created."; - DLOG_IF(ERROR, !device_id.empty()) + DLOG_IF(ERROR, !device_id.empty() && + device_id != AudioManagerBase::kDefaultDeviceId) << "Opening by device id not supported by WASAPIUnifiedStream"; return new WASAPIUnifiedStream(this, params, input_device_id); } - return new WASAPIAudioOutputStream(this, device_id, params, eConsole); + // Pass an empty string to indicate that we want the default device + // since we consistently only check for an empty string in + // WASAPIAudioOutputStream. + return new WASAPIAudioOutputStream(this, + device_id == AudioManagerBase::kDefaultDeviceId ? + std::string() : device_id, + params, eConsole); } // Factory for the implementations of AudioInputStream for AUDIO_PCM_LINEAR @@ -454,14 +462,14 @@ AudioParameters AudioManagerWin::GetPreferredOutputStreamParameters( // 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. + // TODO(henrika): 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. Then here, we can check the layout from the data we + // already hold. if (CoreAudioUtil::IsChannelLayoutSupported( - eRender, eConsole, input_params.channel_layout())) { + output_device_id, eRender, eConsole, + input_params.channel_layout())) { // Open up using the same channel layout as the source if it is // supported by the hardware. channel_layout = input_params.channel_layout(); diff --git a/media/audio/win/audio_unified_win.cc b/media/audio/win/audio_unified_win.cc index 5c1594e..848678d 100644 --- a/media/audio/win/audio_unified_win.cc +++ b/media/audio/win/audio_unified_win.cc @@ -51,23 +51,6 @@ static const char kUnifiedAudioDebugFileName[] = "unified_win_debug.txt"; static const char kUnifiedAudioParamsFileName[] = "unified_win_params.txt"; #endif -typedef uint32 ChannelConfig; - -// Retrieves an integer mask which corresponds to the channel layout the -// audio engine uses for its internal processing/mixing of shared-mode -// streams. This mask indicates which channels are present in the multi- -// channel stream. The least significant bit corresponds with the Front Left -// speaker, the next least significant bit corresponds to the Front Right -// speaker, and so on, continuing in the order defined in KsMedia.h. -// See http://msdn.microsoft.com/en-us/library/windows/hardware/ff537083(v=vs.85).aspx -// for more details. -static ChannelConfig GetChannelConfig(EDataFlow data_flow) { - WAVEFORMATPCMEX format; - return SUCCEEDED(media::CoreAudioUtil::GetDefaultSharedModeMixFormat( - data_flow, eConsole, &format)) ? - static_cast<int>(format.dwChannelMask) : 0; -} - // Use the acquired IAudioClock interface to derive a time stamp of the audio // sample which is currently playing through the speakers. static double SpeakerStreamPosInMilliseconds(IAudioClock* clock) { @@ -575,8 +558,9 @@ void WASAPIUnifiedStream::SetIOFormats(const AudioParameters& input_params, // Add the parts which are unique to WAVE_FORMAT_EXTENSIBLE. // Note that we always open up using the native channel layout. (*xformat).Samples.wValidBitsPerSample = format->wBitsPerSample; - (*xformat).dwChannelMask = (n == 0) ? - GetChannelConfig(eCapture) : GetChannelConfig(eRender); + (*xformat).dwChannelMask = + CoreAudioUtil::GetChannelConfig( + std::string(), n == 0 ? eCapture : eRender); (*xformat).SubFormat = KSDATAFORMAT_SUBTYPE_PCM; } diff --git a/media/audio/win/core_audio_util_win.cc b/media/audio/win/core_audio_util_win.cc index 4adfdda..4771460 100644 --- a/media/audio/win/core_audio_util_win.cc +++ b/media/audio/win/core_audio_util_win.cc @@ -25,8 +25,6 @@ namespace media { enum { KSAUDIO_SPEAKER_UNSUPPORTED = 0 }; -typedef uint32 ChannelConfig; - // Converts Microsoft's channel configuration to ChannelLayout. // This mapping is not perfect but the best we can do given the current // ChannelLayout enumerator and the Windows-specific speaker configurations @@ -401,7 +399,7 @@ std::string CoreAudioUtil::GetMatchingOutputDeviceID( ScopedComPtr<IMMDevice> output_device; for (UINT i = 0; i < count; ++i) { collection->Item(i, output_device.Receive()); - std::string output_controller_id(CoreAudioUtil::GetAudioControllerID( + std::string output_controller_id(GetAudioControllerID( output_device, enumerator)); if (output_controller_id == controller_id) break; @@ -478,6 +476,18 @@ ScopedComPtr<IAudioClient> CoreAudioUtil::CreateDefaultClient( ScopedComPtr<IAudioClient>()); } +ScopedComPtr<IAudioClient> CoreAudioUtil::CreateClient( + const std::string& device_id, EDataFlow data_flow, ERole role) { + if (device_id.empty()) + return CreateDefaultClient(data_flow, role); + + ScopedComPtr<IMMDevice> device(CreateDevice(device_id)); + if (!device) + return ScopedComPtr<IAudioClient>(); + + return CreateClient(device); +} + HRESULT CoreAudioUtil::GetSharedModeMixFormat( IAudioClient* client, WAVEFORMATPCMEX* format) { DCHECK(IsSupported()); @@ -496,18 +506,6 @@ HRESULT CoreAudioUtil::GetSharedModeMixFormat( return hr; } -HRESULT CoreAudioUtil::GetDefaultSharedModeMixFormat( - EDataFlow data_flow, ERole role, WAVEFORMATPCMEX* format) { - DCHECK(IsSupported()); - ScopedComPtr<IAudioClient> client(CreateDefaultClient(data_flow, role)); - if (!client) { - // Map NULL-pointer to new error code which can be different from the - // actual error code. The exact value is not important here. - return AUDCLNT_E_ENDPOINT_CREATE_FAILED; - } - return CoreAudioUtil::GetSharedModeMixFormat(client, format); -} - bool CoreAudioUtil::IsFormatSupported(IAudioClient* client, AUDCLNT_SHAREMODE share_mode, const WAVEFORMATPCMEX* format) { @@ -529,18 +527,20 @@ bool CoreAudioUtil::IsFormatSupported(IAudioClient* client, return (hr == S_OK); } -bool CoreAudioUtil::IsChannelLayoutSupported(EDataFlow data_flow, ERole role, +bool CoreAudioUtil::IsChannelLayoutSupported(const std::string& device_id, + EDataFlow data_flow, + ERole role, ChannelLayout channel_layout) { DCHECK(IsSupported()); // First, get the preferred mixing format for shared mode streams. - ScopedComPtr<IAudioClient> client(CreateDefaultClient(data_flow, role)); + ScopedComPtr<IAudioClient> client(CreateClient(device_id, data_flow, role)); if (!client) return false; WAVEFORMATPCMEX format; - HRESULT hr = CoreAudioUtil::GetSharedModeMixFormat(client, &format); + HRESULT hr = GetSharedModeMixFormat(client, &format); if (FAILED(hr)) return false; @@ -684,6 +684,18 @@ HRESULT CoreAudioUtil::GetPreferredAudioParameters( return GetPreferredAudioParameters(client, params); } +ChannelConfig CoreAudioUtil::GetChannelConfig(const std::string& device_id, + EDataFlow data_flow) { + ScopedComPtr<IAudioClient> client( + CreateClient(device_id, data_flow, eConsole)); + + WAVEFORMATPCMEX format = {0}; + if (!client || FAILED(GetSharedModeMixFormat(client, &format))) + return 0; + + return static_cast<ChannelConfig>(format.dwChannelMask); +} + HRESULT CoreAudioUtil::SharedModeInitialize(IAudioClient* client, const WAVEFORMATPCMEX* format, HANDLE event_handle, diff --git a/media/audio/win/core_audio_util_win.h b/media/audio/win/core_audio_util_win.h index cdf6dfb..a210af9 100644 --- a/media/audio/win/core_audio_util_win.h +++ b/media/audio/win/core_audio_util_win.h @@ -26,6 +26,12 @@ using base::win::ScopedComPtr; namespace media { + +// Represents audio channel configuration constants as understood by Windows. +// E.g. KSAUDIO_SPEAKER_MONO. For a list of possible values see: +// http://msdn.microsoft.com/en-us/library/windows/hardware/ff537083(v=vs.85).aspx +typedef uint32 ChannelConfig; + class MEDIA_EXPORT CoreAudioUtil { public: // Returns true if Windows Core Audio is supported. @@ -106,7 +112,7 @@ class MEDIA_EXPORT CoreAudioUtil { // manage the flow of audio data between the application and an audio endpoint // device. - // Create an IAudioClient interface for the default IMMDevice where + // Create an IAudioClient instance for the default IMMDevice where // flow direction and role is define by |data_flow| and |role|. // The IAudioClient interface enables a client to create and initialize an // audio stream between an audio application and the audio engine (for a @@ -115,6 +121,12 @@ class MEDIA_EXPORT CoreAudioUtil { static ScopedComPtr<IAudioClient> CreateDefaultClient(EDataFlow data_flow, ERole role); + // Create an IAudioClient instance for a specific device _or_ the default + // device if |device_id| is empty. + static ScopedComPtr<IAudioClient> CreateClient(const std::string& device_id, + EDataFlow data_flow, + ERole role); + // Create an IAudioClient interface for an existing IMMDevice given by // |audio_device|. Flow direction and role is define by the |audio_device|. static ScopedComPtr<IAudioClient> CreateClient(IMMDevice* audio_device); @@ -126,13 +138,6 @@ class MEDIA_EXPORT CoreAudioUtil { static HRESULT GetSharedModeMixFormat(IAudioClient* client, WAVEFORMATPCMEX* format); - // Get the mix format that the audio engine uses internally for processing - // of shared-mode streams using the default IMMDevice where flow direction - // and role is define by |data_flow| and |role|. - static HRESULT GetDefaultSharedModeMixFormat(EDataFlow data_flow, - ERole role, - WAVEFORMATPCMEX* format); - // Returns true if the specified |client| supports the format in |format| // for the given |share_mode| (shared or exclusive). static bool IsFormatSupported(IAudioClient* client, @@ -144,7 +149,9 @@ class MEDIA_EXPORT CoreAudioUtil { // and |role|. If this method returns true for a certain channel layout, it // means that SharedModeInitialize() will succeed using a format based on // the preferred format where the channel layout has been modified. - static bool IsChannelLayoutSupported(EDataFlow data_flow, ERole role, + static bool IsChannelLayoutSupported(const std::string& device_id, + EDataFlow data_flow, + ERole role, ChannelLayout channel_layout); // For a shared-mode stream, the audio engine periodically processes the @@ -170,6 +177,19 @@ class MEDIA_EXPORT CoreAudioUtil { static HRESULT GetPreferredAudioParameters(const std::string& device_id, AudioParameters* params); + // Retrieves an integer mask which corresponds to the channel layout the + // audio engine uses for its internal processing/mixing of shared-mode + // streams. This mask indicates which channels are present in the multi- + // channel stream. The least significant bit corresponds with the Front Left + // speaker, the next least significant bit corresponds to the Front Right + // speaker, and so on, continuing in the order defined in KsMedia.h. + // See http://msdn.microsoft.com/en-us/library/windows/hardware/ff537083(v=vs.85).aspx + // for more details. + // To get the channel config of the default device, pass an empty string + // for |device_id|. + static ChannelConfig GetChannelConfig(const std::string& device_id, + EDataFlow data_flow); + // After activating an IAudioClient interface on an audio endpoint device, // the client must initialize it once, and only once, to initialize the audio // stream between the client and the device. In shared mode, the client diff --git a/media/audio/win/core_audio_util_win_unittest.cc b/media/audio/win/core_audio_util_win_unittest.cc index abef868..e9ed0c4 100644 --- a/media/audio/win/core_audio_util_win_unittest.cc +++ b/media/audio/win/core_audio_util_win_unittest.cc @@ -274,7 +274,7 @@ TEST_F(CoreAudioUtilWinTest, IsChannelLayoutSupported) { EXPECT_TRUE(SUCCEEDED(hr)); EXPECT_TRUE(mix_params.IsValid()); EXPECT_TRUE(CoreAudioUtil::IsChannelLayoutSupported( - eRender, eConsole, mix_params.channel_layout())); + std::string(), eRender, eConsole, mix_params.channel_layout())); // Check if it is possible to modify the channel layout to stereo for a // device which reports that it prefers to be openen up in an other @@ -284,7 +284,7 @@ TEST_F(CoreAudioUtilWinTest, IsChannelLayoutSupported) { // TODO(henrika): it might be too pessimistic to assume false as return // value here. EXPECT_FALSE(CoreAudioUtil::IsChannelLayoutSupported( - eRender, eConsole, channel_layout)); + std::string(), eRender, eConsole, channel_layout)); } } |