Commit 4ee1f756 authored by henrika@chromium.org's avatar henrika@chromium.org

This CL adds support for experimental exclusive-mode streaming to...

This CL adds support for experimental exclusive-mode streaming to WASAPIAudioOutputStream. Enabling the flag "enable-exclusive-mode" will ensure that output audio streaming on Windows runs in exclusive mode (if the user has allowed it).

Initial tests shows that we can reach latencies of about 3.33ms for 48kHz. As a comparison, for shared-mode, the total latency is ~35ms (even if the time between each OnMoreData() callback is ~10ms).

BUG=133483
TEST=media_unittests --enable-exclusive-audio --gtest_filter=WinAudioOutputTest*

Review URL: https://chromiumcodereview.appspot.com/10575017

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@148731 0039d316-1c4b-4281-b951-d872f2087c98
parent 288235fb
......@@ -20,20 +20,20 @@
#include "base/logging.h"
#include "base/shared_memory.h"
#include "base/time.h"
#if defined(OS_WIN)
#include "base/sys_info.h"
#include "base/win/windows_version.h"
#include "media/audio/audio_manager_base.h"
#endif
#include "media/audio/audio_parameters.h"
#include "media/audio/audio_util.h"
#if defined(OS_MACOSX)
#include "media/audio/mac/audio_low_latency_input_mac.h"
#include "media/audio/mac/audio_low_latency_output_mac.h"
#endif
#if defined(OS_WIN)
#elif defined(OS_WIN)
#include "base/command_line.h"
#include "base/sys_info.h"
#include "base/win/windows_version.h"
#include "media/audio/audio_manager_base.h"
#include "media/audio/win/audio_low_latency_input_win.h"
#include "media/audio/win/audio_low_latency_output_win.h"
#include "media/base/media_switches.h"
#endif
using base::subtle::Atomic32;
......@@ -351,16 +351,28 @@ int GetAudioHardwareSampleRate() {
return 48000;
}
// TODO(crogers): tune this rate 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.
const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
if (cmd_line->HasSwitch(switches::kEnableExclusiveAudio)) {
// This sample rate will be combined with a buffer size of 256 samples
// (see GetAudioHardwareBufferSize()), which corresponds to an output
// delay of ~5.33ms.
return 48000;
}
// Hardware sample-rate on Windows can be configured, so we must query.
// TODO(henrika): improve possibility to specify audio endpoint.
// Use the default device (same as for Wave) for now to be compatible.
// TODO(henrika): improve possibility to specify an audio endpoint.
// Use the default device (same as for Wave) for now to be compatible
// or possibly remove the ERole argument completely until it is in use.
return WASAPIAudioOutputStream::HardwareSampleRate(eConsole);
#elif defined(OS_ANDROID)
return 16000;
#else
// Hardware for Linux is nearly always 48KHz.
// TODO(crogers) : return correct value in rare non-48KHz cases.
return 48000;
// Hardware for Linux is nearly always 48KHz.
// TODO(crogers) : return correct value in rare non-48KHz cases.
return 48000;
#endif
}
......@@ -397,6 +409,15 @@ size_t GetAudioHardwareBufferSize() {
// and assume 48kHz as default sample rate.
return 2048;
}
// TODO(crogers): tune this size to best possible WebAudio performance.
// WebRTC always uses 10ms for Windows and does not call this method.
// Note that exclusive mode is experimental.
const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
if (cmd_line->HasSwitch(switches::kEnableExclusiveAudio)) {
return 256;
}
// This call must be done on a COM thread configured as MTA.
// TODO(tommi): http://code.google.com/p/chromium/issues/detail?id=103835.
int mixing_sample_rate =
......
......@@ -112,6 +112,27 @@
// - All callback methods from the IMMNotificationClient interface will be
// called on a Windows-internal MMDevice thread.
//
// Experimental exclusive mode:
//
// - It is possible to open up a stream in exclusive mode by using the
// --enable-exclusive-mode command line flag.
// - The internal buffering scheme is less flexible for exclusive streams.
// Hence, some manual tuning will be required before deciding what frame
// size to use. See the WinAudioOutputTest unit test for more details.
// - If an application opens a stream in exclusive mode, the application has
// exclusive use of the audio endpoint device that plays the stream.
// - Exclusive-mode should only be utilized when the lowest possible latency
// is important.
// - In exclusive mode, the client can choose to open the stream in any audio
// format that the endpoint device supports, i.e. not limited to the device's
// current (default) configuration.
// - Initial measurements on Windows 7 (HP Z600 workstation) have shown that
// the lowest possible latencies we can achieve on this machine are:
// o ~3.3333ms @ 48kHz <=> 160 audio frames per buffer.
// o ~3.6281ms @ 44.1kHz <=> 160 audio frames per buffer.
// - See http://msdn.microsoft.com/en-us/library/windows/desktop/dd370844(v=vs.85).aspx
// for more details.
#ifndef MEDIA_AUDIO_WIN_AUDIO_LOW_LATENCY_OUTPUT_WIN_H_
#define MEDIA_AUDIO_WIN_AUDIO_LOW_LATENCY_OUTPUT_WIN_H_
......@@ -163,8 +184,13 @@ class MEDIA_EXPORT WASAPIAudioOutputStream
// Retrieves the stream format that the audio engine uses for its internal
// processing/mixing of shared-mode streams.
// This method should not be used in combination with exclusive-mode streams.
static int HardwareSampleRate(ERole device_role);
// Returns AUDCLNT_SHAREMODE_EXCLUSIVE if --enable-exclusive-mode is used
// as command-line flag and AUDCLNT_SHAREMODE_SHARED otherwise (default).
static AUDCLNT_SHAREMODE GetShareMode();
bool started() const { return started_; }
private:
......@@ -206,12 +232,19 @@ class MEDIA_EXPORT WASAPIAudioOutputStream
void HandleError(HRESULT err);
// The Open() method is divided into these sub methods.
HRESULT SetRenderDevice(ERole device_role);
HRESULT SetRenderDevice();
HRESULT ActivateRenderDevice();
HRESULT GetAudioEngineStreamFormat();
bool DesiredFormatIsSupported();
HRESULT InitializeAudioEngine();
// Called when the device will be opened in shared mode and use the
// internal audio engine's mix format.
HRESULT SharedModeInitialization();
// Called when the device will be opened in exclusive mode and use the
// application specified format.
HRESULT ExclusiveModeInitialization();
// Converts unique endpoint ID to user-friendly device name.
std::string GetDeviceName(LPCWSTR device_id) const;
......@@ -222,6 +255,8 @@ class MEDIA_EXPORT WASAPIAudioOutputStream
// new default audio device.
bool RestartRenderingUsingNewDefaultDevice();
AUDCLNT_SHAREMODE share_mode() const { return share_mode_; }
// Initializes the COM library for use by the calling thread and sets the
// thread's concurrency model to multi-threaded.
base::win::ScopedCOMInitializer com_init_;
......@@ -276,6 +311,11 @@ class MEDIA_EXPORT WASAPIAudioOutputStream
// Defines the role that the system has assigned to an audio endpoint device.
ERole device_role_;
// The sharing mode for the connection.
// Valid values are AUDCLNT_SHAREMODE_SHARED and AUDCLNT_SHAREMODE_EXCLUSIVE
// where AUDCLNT_SHAREMODE_SHARED is the default.
AUDCLNT_SHAREMODE share_mode_;
// Counts the number of audio frames written to the endpoint buffer.
UINT64 num_written_frames_;
......
......@@ -23,6 +23,15 @@ const char kUseCras[] = "use-cras";
const char kUsePulseAudio[] = "use-pulseaudio";
#endif
#if defined(OS_WIN)
// Use exclusive mode audio streaming for Windows Vista and higher.
// Leads to lower latencies for audio streams which uses the
// AudioParameters::AUDIO_PCM_LOW_LATENCY audio path.
// See http://msdn.microsoft.com/en-us/library/windows/desktop/dd370844(v=vs.85).aspx
// for details.
const char kEnableExclusiveAudio[] = "enable-exclusive-audio";
#endif
// Set number of threads to use for video decoding.
const char kVideoThreads[] = "video-threads";
......
......@@ -25,6 +25,10 @@ MEDIA_EXPORT extern const char kUseCras[];
MEDIA_EXPORT extern const char kUsePulseAudio[];
#endif
#if defined(OS_WIN)
MEDIA_EXPORT extern const char kEnableExclusiveAudio[];
#endif
MEDIA_EXPORT extern const char kVideoThreads[];
MEDIA_EXPORT extern const char kDisableAudioMixer[];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment