summaryrefslogtreecommitdiffstats
path: root/media/audio
diff options
context:
space:
mode:
Diffstat (limited to 'media/audio')
-rw-r--r--media/audio/win/audio_low_latency_output_win.cc66
-rw-r--r--media/audio/win/audio_low_latency_output_win.h11
-rw-r--r--media/audio/win/audio_manager_win.cc28
-rw-r--r--media/audio/win/audio_unified_win.cc22
-rw-r--r--media/audio/win/core_audio_util_win.cc48
-rw-r--r--media/audio/win/core_audio_util_win.h38
-rw-r--r--media/audio/win/core_audio_util_win_unittest.cc4
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));
}
}