Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1076)

Unified Diff: media/audio/win/audio_manager_win.cc

Issue 2646423005: Remove the wave based audio capture implementation for Windows (Closed)
Patch Set: Minor cleanup + documentation Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « media/audio/win/audio_manager_win.h ('k') | media/audio/win/core_audio_util_win.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 4c46fc1155ab111c20f6eade1b559709736eca7f..b5b262fb414afd8158980ca12e84270969c68633 100644
--- a/media/audio/win/audio_manager_win.cc
+++ b/media/audio/win/audio_manager_win.cc
@@ -31,7 +31,6 @@
#include "media/audio/win/audio_low_latency_output_win.h"
#include "media/audio/win/core_audio_util_win.h"
#include "media/audio/win/device_enumeration_win.h"
-#include "media/audio/win/wavein_input_win.h"
#include "media/audio/win/waveout_output_win.h"
#include "media/base/audio_parameters.h"
#include "media/base/bind_to_current_loop.h"
@@ -44,8 +43,18 @@
#define DRV_QUERYDEVICEINTERFACE 0x80c
#define DRVM_MAPPER_PREFERRED_GET 0x2015
#define DRV_QUERYDEVICEINTERFACESIZE 0x80d
-DEFINE_GUID(AM_KSCATEGORY_AUDIO, 0x6994ad04, 0x93ef, 0x11d0,
- 0xa3, 0xcc, 0x00, 0xa0, 0xc9, 0x22, 0x31, 0x96);
+DEFINE_GUID(AM_KSCATEGORY_AUDIO,
+ 0x6994ad04,
+ 0x93ef,
+ 0x11d0,
+ 0xa3,
+ 0xcc,
+ 0x00,
+ 0xa0,
+ 0xc9,
+ 0x22,
+ 0x31,
+ 0x96);
namespace media {
@@ -56,13 +65,6 @@ static const int kMaxOutputStreams = 50;
// right drivers, but graceful error handling is needed.
static const int kWinMaxChannels = 8;
-// We use 3 buffers for recording audio so that if a recording callback takes
-// some time to return we won't lose audio. More buffers while recording are
-// ok because they don't introduce any delay in recording, unlike in playback
-// where you first need to fill in that number of buffers before starting to
-// play.
-static const int kNumInputBuffers = 3;
-
// Buffer size to use for input and output stream when a proper size can't be
// determined from the system
static const int kFallbackBufferSize = 2048;
@@ -94,7 +96,8 @@ static base::string16 GetDeviceAndDriverInfo(HDEVINFO device_info,
if (SetupDiEnumDriverInfo(device_info, device_data, SPDIT_COMPATDRIVER, 0,
&driver_data)) {
DWORDLONG version = driver_data.DriverVersion;
- device_and_driver_info = base::string16(driver_data.Description) + L" v" +
+ device_and_driver_info =
+ base::string16(driver_data.Description) + L" v" +
base::IntToString16(GetVersionPartAsInt((version >> 48))) + L"." +
base::IntToString16(GetVersionPartAsInt((version >> 32))) + L"." +
base::IntToString16(GetVersionPartAsInt((version >> 16))) + L"." +
@@ -134,13 +137,13 @@ AudioManagerWin::AudioManagerWin(
AudioLogFactory* audio_log_factory)
: AudioManagerBase(std::move(task_runner),
std::move(worker_task_runner),
- audio_log_factory),
- // |CoreAudioUtil::IsSupported()| uses static variables to avoid doing
- // multiple initializations. This is however not thread safe.
- // So, here we call it explicitly before we kick off the audio thread
- // or do any other work.
- enumeration_type_(CoreAudioUtil::IsSupported() ? kMMDeviceEnumeration
- : kWaveEnumeration) {
+ audio_log_factory) {
+ // |CoreAudioUtil::IsSupported()| uses static variables to avoid doing
+ // multiple initializations. This is however not thread safe.
+ // So, here we call it explicitly before we kick off the audio thread
+ // or do any other work.
+ CoreAudioUtil::IsSupported();
+
SetMaxOutputStreamsAllowed(kMaxOutputStreams);
// WARNING: This is executed on the UI loop, do not add any code here which
@@ -149,8 +152,9 @@ AudioManagerWin::AudioManagerWin(
// Task must be posted last to avoid races from handing out "this" to the
// audio thread.
- GetTaskRunner()->PostTask(FROM_HERE, base::Bind(
- &AudioManagerWin::InitializeOnAudioThread, base::Unretained(this)));
+ GetTaskRunner()->PostTask(
+ FROM_HERE, base::Bind(&AudioManagerWin::InitializeOnAudioThread,
+ base::Unretained(this)));
}
AudioManagerWin::~AudioManagerWin() {
@@ -168,13 +172,10 @@ bool AudioManagerWin::HasAudioInputDevices() {
void AudioManagerWin::InitializeOnAudioThread() {
DCHECK(GetTaskRunner()->BelongsToCurrentThread());
- if (core_audio_supported()) {
- // AudioDeviceListenerWin must be initialized on a COM thread and should
- // only be used if WASAPI / Core Audio is supported.
- output_device_listener_.reset(new AudioDeviceListenerWin(BindToCurrentLoop(
- base::Bind(&AudioManagerWin::NotifyAllOutputDeviceChangeListeners,
- base::Unretained(this)))));
- }
+ // AudioDeviceListenerWin must be initialized on a COM thread.
+ output_device_listener_.reset(new AudioDeviceListenerWin(BindToCurrentLoop(
+ base::Bind(&AudioManagerWin::NotifyAllOutputDeviceChangeListeners,
+ base::Unretained(this)))));
}
base::string16 AudioManagerWin::GetAudioInputDeviceModel() {
@@ -193,10 +194,9 @@ base::string16 AudioManagerWin::GetAudioInputDeviceModel() {
return base::string16(); // No audio capture device.
base::string16 device_interface_name;
- base::string16::value_type* name_ptr = base::WriteInto(&device_interface_name,
- device_interface_name_size / bytes_in_char16);
- waveInMessage(reinterpret_cast<HWAVEIN>(device_id),
- DRV_QUERYDEVICEINTERFACE,
+ base::string16::value_type* name_ptr = base::WriteInto(
+ &device_interface_name, device_interface_name_size / bytes_in_char16);
+ waveInMessage(reinterpret_cast<HWAVEIN>(device_id), DRV_QUERYDEVICEINTERFACE,
reinterpret_cast<DWORD_PTR>(name_ptr),
static_cast<DWORD_PTR>(device_interface_name_size));
@@ -227,10 +227,9 @@ base::string16 AudioManagerWin::GetAudioInputDeviceModel() {
reinterpret_cast<SP_DEVICE_INTERFACE_DETAIL_DATA*>(
interface_detail_buffer.get());
interface_detail->cbSize = interface_detail_size;
- if (!SetupDiGetDeviceInterfaceDetail(device_info, &interface_data,
- interface_detail,
- interface_detail_size, NULL,
- &device_data))
+ if (!SetupDiGetDeviceInterfaceDetail(
+ device_info, &interface_data, interface_detail,
+ interface_detail_size, NULL, &device_data))
return base::string16();
bool device_found = (device_interface_name == interface_detail->DevicePath);
@@ -243,46 +242,25 @@ base::string16 AudioManagerWin::GetAudioInputDeviceModel() {
}
void AudioManagerWin::ShowAudioInputSettings() {
- std::wstring program;
- std::string argument;
- if (!core_audio_supported()) {
- program = L"sndvol32.exe";
- argument = "-R";
- } else {
- program = L"control.exe";
- argument = "mmsys.cpl,,1";
- }
-
base::FilePath path;
PathService::Get(base::DIR_SYSTEM, &path);
- path = path.Append(program);
+ path = path.Append(L"control.exe");
base::CommandLine command_line(path);
- command_line.AppendArg(argument);
+ command_line.AppendArg("mmsys.cpl,,1");
base::LaunchProcess(command_line, base::LaunchOptions());
}
-void AudioManagerWin::GetAudioDeviceNamesImpl(
- bool input,
- AudioDeviceNames* device_names) {
+void AudioManagerWin::GetAudioDeviceNamesImpl(bool input,
+ AudioDeviceNames* device_names) {
DCHECK(device_names->empty());
// Enumerate all active audio-endpoint capture devices.
- if (enumeration_type() == kWaveEnumeration) {
- // Utilize the Wave API for Windows XP.
- if (input)
- GetInputDeviceNamesWinXP(device_names);
- else
- GetOutputDeviceNamesWinXP(device_names);
- } else {
- // Utilize the MMDevice API (part of Core Audio) for Vista and higher.
- if (input)
- GetInputDeviceNamesWin(device_names);
- else
- GetOutputDeviceNamesWin(device_names);
- }
+ if (input)
+ GetInputDeviceNamesWin(device_names);
+ else
+ GetOutputDeviceNamesWin(device_names);
if (!device_names->empty()) {
- if (enumeration_type() == kMMDeviceEnumeration)
- device_names->push_front(AudioDeviceName::CreateCommunications());
+ device_names->push_front(AudioDeviceName::CreateCommunications());
// Always add default device parameters as first element.
device_names->push_front(AudioDeviceName::CreateDefault());
@@ -300,18 +278,14 @@ void AudioManagerWin::GetAudioOutputDeviceNames(
AudioParameters AudioManagerWin::GetInputStreamParameters(
const std::string& device_id) {
- HRESULT hr = E_FAIL;
AudioParameters parameters;
- if (core_audio_supported()) {
- hr = CoreAudioUtil::GetPreferredAudioParameters(device_id, false,
- &parameters);
- }
+ HRESULT hr =
+ CoreAudioUtil::GetPreferredAudioParameters(device_id, false, &parameters);
if (FAILED(hr) || !parameters.IsValid()) {
- // Windows Wave implementation is being used.
- parameters =
- AudioParameters(AudioParameters::AUDIO_PCM_LINEAR,
- CHANNEL_LAYOUT_STEREO, 48000, 16, kFallbackBufferSize);
+ LOG(WARNING) << "Unable to get preferred audio params for " << device_id
+ << " 0x" << std::hex << hr;
+ return parameters;
}
int user_buffer_size = GetUserBufferSize();
@@ -323,11 +297,6 @@ AudioParameters AudioManagerWin::GetInputStreamParameters(
std::string AudioManagerWin::GetAssociatedOutputDeviceID(
const std::string& input_device_id) {
- if (!core_audio_supported()) {
- NOTIMPLEMENTED()
- << "GetAssociatedOutputDeviceID is not supported on this OS";
- return std::string();
- }
return CoreAudioUtil::GetMatchingOutputDeviceID(input_device_id);
}
@@ -345,9 +314,7 @@ AudioOutputStream* AudioManagerWin::MakeLinearOutputStream(
if (params.channels() > kWinMaxChannels)
return NULL;
- return new PCMWaveOutAudioOutputStream(this,
- params,
- NumberOfWaveOutBuffers(),
+ return new PCMWaveOutAudioOutputStream(this, params, NumberOfWaveOutBuffers(),
WAVE_MAPPER);
}
@@ -364,16 +331,6 @@ AudioOutputStream* AudioManagerWin::MakeLowLatencyOutputStream(
if (params.channels() > kWinMaxChannels)
return NULL;
- if (!core_audio_supported()) {
- // Fall back to Windows Wave implementation on Windows XP or lower.
- DLOG_IF(ERROR, !device_id.empty() &&
- device_id != AudioDeviceDescription::kDefaultDeviceId)
- << "Opening by device id not supported by PCMWaveOutAudioOutputStream";
- DVLOG(1) << "Using WaveOut since WASAPI requires at least Vista.";
- return new PCMWaveOutAudioOutputStream(
- this, params, NumberOfWaveOutBuffers(), WAVE_MAPPER);
- }
-
// Pass an empty string to indicate that we want the default device
// since we consistently only check for an empty string in
// WASAPIAudioOutputStream.
@@ -394,7 +351,7 @@ AudioInputStream* AudioManagerWin::MakeLinearInputStream(
const std::string& device_id,
const LogCallback& log_callback) {
DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
- return CreatePCMWaveInAudioInputStream(params, device_id);
+ return MakeLowLatencyInputStream(params, device_id, log_callback);
}
// Factory for the implementations of AudioInputStream for
@@ -403,81 +360,67 @@ AudioInputStream* AudioManagerWin::MakeLowLatencyInputStream(
const AudioParameters& params,
const std::string& device_id,
const LogCallback& log_callback) {
- DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
+ // Used for both AUDIO_PCM_LOW_LATENCY and AUDIO_PCM_LINEAR.
DVLOG(1) << "MakeLowLatencyInputStream: " << device_id;
- AudioInputStream* stream = NULL;
- UMA_HISTOGRAM_BOOLEAN("Media.WindowsCoreAudioInput", core_audio_supported());
- if (!core_audio_supported()) {
- // Fall back to Windows Wave implementation on Windows XP or lower.
- DVLOG(1) << "Using WaveIn since WASAPI requires at least Vista.";
- stream = CreatePCMWaveInAudioInputStream(params, device_id);
- } else {
- stream = new WASAPIAudioInputStream(this, params, device_id);
- }
-
- return stream;
+ return new WASAPIAudioInputStream(this, params, device_id);
}
std::string AudioManagerWin::GetDefaultOutputDeviceID() {
- if (!core_audio_supported())
- return std::string();
return CoreAudioUtil::GetDefaultOutputDeviceID();
}
AudioParameters AudioManagerWin::GetPreferredOutputStreamParameters(
const std::string& output_device_id,
const AudioParameters& input_params) {
- DLOG_IF(ERROR, !core_audio_supported() && !output_device_id.empty())
- << "CoreAudio is required to open non-default devices.";
-
const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO;
int sample_rate = 48000;
int buffer_size = kFallbackBufferSize;
int bits_per_sample = 16;
int effects = AudioParameters::NO_EFFECTS;
- 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 {
- AudioParameters params;
- HRESULT hr = CoreAudioUtil::GetPreferredAudioParameters(
- output_device_id.empty() ? GetDefaultOutputDeviceID()
- : output_device_id,
- true, &params);
- 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();
- effects = params.effects();
- } else {
- // TODO(tommi): This should never happen really and I'm not sure that
- // setting use_input_params is the right thing to do since WASAPI i
- // definitely supported (see core_audio_supported() above) and
- // |use_input_params| is only for cases when it isn't supported.
- DLOG(ERROR) << "GetPreferredAudioParameters failed: " << std::hex << hr;
- use_input_params = true;
- }
+
+ // TODO(henrika): Remove kEnableExclusiveAudio and related code. It doesn't
+ // look like it's used.
+ 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 {
+ AudioParameters params;
+ HRESULT hr = CoreAudioUtil::GetPreferredAudioParameters(
+ output_device_id.empty() ? GetDefaultOutputDeviceID()
+ : output_device_id,
+ true, &params);
+ if (FAILED(hr)) {
+ // This can happen when CoreAudio isn't supported or available
+ // (e.g. certain installations of Windows Server 2008 R2).
+ // Instead of returning the input_params, we'll return invalid
+ // AudioParameters to make sure that an attempt to create this output
+ // stream, won't succeed. This behavior is also consistent with
+ // GetInputStreamParameters.
+ DLOG(ERROR) << "GetPreferredAudioParameters failed: " << std::hex << hr;
+ return AudioParameters();
}
+
+ bits_per_sample = params.bits_per_sample();
+ buffer_size = params.frames_per_buffer();
+ channel_layout = params.channel_layout();
+ sample_rate = params.sample_rate();
+ effects = params.effects();
}
if (input_params.IsValid()) {
// If the user has enabled checking supported channel layouts or we don't
// have a valid channel layout yet, try to use the input layout. See bugs
// http://crbug.com/259165 and http://crbug.com/311906 for more details.
- if (core_audio_supported() &&
- (cmd_line->HasSwitch(switches::kTrySupportedChannelLayouts) ||
- channel_layout == CHANNEL_LAYOUT_UNSUPPORTED)) {
+ if (cmd_line->HasSwitch(switches::kTrySupportedChannelLayouts) ||
+ channel_layout == CHANNEL_LAYOUT_UNSUPPORTED) {
// 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
@@ -501,17 +444,6 @@ AudioParameters AudioManagerWin::GetPreferredOutputStreamParameters(
}
effects |= input_params.effects();
- if (use_input_params) {
- // If WASAPI isn't supported we'll fallback to WaveOut, which will take
- // care of resampling and bits per sample changes. By setting these
- // equal to the input values, AudioOutputResampler will skip resampling
- // and bit per sample differences (since the input parameters will match
- // the output parameters).
- bits_per_sample = input_params.bits_per_sample();
- buffer_size = input_params.frames_per_buffer();
- channel_layout = input_params.channel_layout();
- sample_rate = input_params.sample_rate();
- }
}
int user_buffer_size = GetUserBufferSize();
@@ -524,25 +456,7 @@ AudioParameters AudioManagerWin::GetPreferredOutputStreamParameters(
return params;
}
-AudioInputStream* AudioManagerWin::CreatePCMWaveInAudioInputStream(
- const AudioParameters& params,
- const std::string& device_id) {
- std::string xp_device_id = device_id;
- if (device_id != AudioDeviceDescription::kDefaultDeviceId &&
- enumeration_type_ == kMMDeviceEnumeration) {
- xp_device_id = ConvertToWinXPInputDeviceId(device_id);
- if (xp_device_id.empty()) {
- DLOG(ERROR) << "Cannot find a waveIn device which matches the device ID "
- << device_id;
- return NULL;
- }
- }
-
- return new PCMWaveInAudioInputStream(this, params, kNumInputBuffers,
- xp_device_id);
-}
-
-/// static
+// static
ScopedAudioManagerPtr CreateAudioManager(
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner,
« no previous file with comments | « media/audio/win/audio_manager_win.h ('k') | media/audio/win/core_audio_util_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698