audio_low_latency_output_win.h revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5// Implementation of AudioOutputStream for Windows using Windows Core Audio 6// WASAPI for low latency rendering. 7// 8// Overview of operation and performance: 9// 10// - An object of WASAPIAudioOutputStream is created by the AudioManager 11// factory. 12// - Next some thread will call Open(), at that point the underlying 13// Core Audio APIs are utilized to create two WASAPI interfaces called 14// IAudioClient and IAudioRenderClient. 15// - Then some thread will call Start(source). 16// A thread called "wasapi_render_thread" is started and this thread listens 17// on an event signal which is set periodically by the audio engine to signal 18// render events. As a result, OnMoreData() will be called and the registered 19// client is then expected to provide data samples to be played out. 20// - At some point, a thread will call Stop(), which stops and joins the 21// render thread and at the same time stops audio streaming. 22// - The same thread that called stop will call Close() where we cleanup 23// and notify the audio manager, which likely will destroy this object. 24// - A total typical delay of 35 ms contains three parts: 25// o Audio endpoint device period (~10 ms). 26// o Stream latency between the buffer and endpoint device (~5 ms). 27// o Endpoint buffer (~20 ms to ensure glitch-free rendering). 28// 29// Implementation notes: 30// 31// - The minimum supported client is Windows Vista. 32// - This implementation is single-threaded, hence: 33// o Construction and destruction must take place from the same thread. 34// o All APIs must be called from the creating thread as well. 35// - It is required to first acquire the native audio parameters of the default 36// output device and then use the same rate when creating this object. Use 37// e.g. WASAPIAudioOutputStream::HardwareSampleRate() to retrieve the sample 38// rate. Open() will fail unless "perfect" audio parameters are utilized. 39// - Calling Close() also leads to self destruction. 40// - Support for 8-bit audio has not yet been verified and tested. 41// 42// Core Audio API details: 43// 44// - The public API methods (Open(), Start(), Stop() and Close()) must be 45// called on constructing thread. The reason is that we want to ensure that 46// the COM environment is the same for all API implementations. 47// - Utilized MMDevice interfaces: 48// o IMMDeviceEnumerator 49// o IMMDevice 50// - Utilized WASAPI interfaces: 51// o IAudioClient 52// o IAudioRenderClient 53// - The stream is initialized in shared mode and the processing of the 54// audio buffer is event driven. 55// - The Multimedia Class Scheduler service (MMCSS) is utilized to boost 56// the priority of the render thread. 57// - Audio-rendering endpoint devices can have three roles: 58// Console (eConsole), Communications (eCommunications), and Multimedia 59// (eMultimedia). Search for "Device Roles" on MSDN for more details. 60// 61// Threading details: 62// 63// - It is assumed that this class is created on the audio thread owned 64// by the AudioManager. 65// - It is a requirement to call the following methods on the same audio 66// thread: Open(), Start(), Stop(), and Close(). 67// - Audio rendering is performed on the audio render thread, owned by this 68// class, and the AudioSourceCallback::OnMoreData() method will be called 69// from this thread. Stream switching also takes place on the audio-render 70// thread. 71// 72// Experimental exclusive mode: 73// 74// - It is possible to open up a stream in exclusive mode by using the 75// --enable-exclusive-audio command line flag. 76// - The internal buffering scheme is less flexible for exclusive streams. 77// Hence, some manual tuning will be required before deciding what frame 78// size to use. See the WinAudioOutputTest unit test for more details. 79// - If an application opens a stream in exclusive mode, the application has 80// exclusive use of the audio endpoint device that plays the stream. 81// - Exclusive-mode should only be utilized when the lowest possible latency 82// is important. 83// - In exclusive mode, the client can choose to open the stream in any audio 84// format that the endpoint device supports, i.e. not limited to the device's 85// current (default) configuration. 86// - Initial measurements on Windows 7 (HP Z600 workstation) have shown that 87// the lowest possible latencies we can achieve on this machine are: 88// o ~3.3333ms @ 48kHz <=> 160 audio frames per buffer. 89// o ~3.6281ms @ 44.1kHz <=> 160 audio frames per buffer. 90// - See http://msdn.microsoft.com/en-us/library/windows/desktop/dd370844(v=vs.85).aspx 91// for more details. 92 93#ifndef MEDIA_AUDIO_WIN_AUDIO_LOW_LATENCY_OUTPUT_WIN_H_ 94#define MEDIA_AUDIO_WIN_AUDIO_LOW_LATENCY_OUTPUT_WIN_H_ 95 96#include <Audioclient.h> 97#include <MMDeviceAPI.h> 98 99#include <string> 100 101#include "base/compiler_specific.h" 102#include "base/memory/scoped_ptr.h" 103#include "base/threading/platform_thread.h" 104#include "base/threading/simple_thread.h" 105#include "base/win/scoped_co_mem.h" 106#include "base/win/scoped_com_initializer.h" 107#include "base/win/scoped_comptr.h" 108#include "base/win/scoped_handle.h" 109#include "media/audio/audio_io.h" 110#include "media/audio/audio_parameters.h" 111#include "media/base/media_export.h" 112 113namespace media { 114 115class AudioManagerWin; 116 117// AudioOutputStream implementation using Windows Core Audio APIs. 118class MEDIA_EXPORT WASAPIAudioOutputStream : 119 public AudioOutputStream, 120 public base::DelegateSimpleThread::Delegate { 121 public: 122 // The ctor takes all the usual parameters, plus |manager| which is the 123 // the audio manager who is creating this object. 124 WASAPIAudioOutputStream(AudioManagerWin* manager, 125 const AudioParameters& params, 126 ERole device_role); 127 128 // The dtor is typically called by the AudioManager only and it is usually 129 // triggered by calling AudioOutputStream::Close(). 130 virtual ~WASAPIAudioOutputStream(); 131 132 // Implementation of AudioOutputStream. 133 virtual bool Open() OVERRIDE; 134 virtual void Start(AudioSourceCallback* callback) OVERRIDE; 135 virtual void Stop() OVERRIDE; 136 virtual void Close() OVERRIDE; 137 virtual void SetVolume(double volume) OVERRIDE; 138 virtual void GetVolume(double* volume) OVERRIDE; 139 140 // Retrieves the number of channels the audio engine uses for its internal 141 // processing/mixing of shared-mode streams for the default endpoint device. 142 static int HardwareChannelCount(); 143 144 // Retrieves the channel layout the audio engine uses for its internal 145 // processing/mixing of shared-mode streams for the default endpoint device. 146 // Note that we convert an internal channel layout mask (see ChannelMask()) 147 // into a Chrome-specific channel layout enumerator in this method, hence 148 // the match might not be perfect. 149 static ChannelLayout HardwareChannelLayout(); 150 151 // Retrieves the sample rate the audio engine uses for its internal 152 // processing/mixing of shared-mode streams for the default endpoint device. 153 static int HardwareSampleRate(); 154 155 // Returns AUDCLNT_SHAREMODE_EXCLUSIVE if --enable-exclusive-mode is used 156 // as command-line flag and AUDCLNT_SHAREMODE_SHARED otherwise (default). 157 static AUDCLNT_SHAREMODE GetShareMode(); 158 159 bool started() const { return render_thread_.get() != NULL; } 160 161 private: 162 // DelegateSimpleThread::Delegate implementation. 163 virtual void Run() OVERRIDE; 164 165 // Core part of the thread loop which controls the actual rendering. 166 // Checks available amount of space in the endpoint buffer and reads 167 // data from the client to fill up the buffer without causing audio 168 // glitches. 169 void RenderAudioFromSource(IAudioClock* audio_clock, UINT64 device_frequency); 170 171 // Issues the OnError() callback to the |sink_|. 172 void HandleError(HRESULT err); 173 174 // Called when the device will be opened in exclusive mode and use the 175 // application specified format. 176 // TODO(henrika): rewrite and move to CoreAudioUtil when removing flag 177 // for exclusive audio mode. 178 HRESULT ExclusiveModeInitialization(IAudioClient* client, 179 HANDLE event_handle, 180 uint32* endpoint_buffer_size); 181 182 // Contains the thread ID of the creating thread. 183 base::PlatformThreadId creating_thread_id_; 184 185 // Our creator, the audio manager needs to be notified when we close. 186 AudioManagerWin* manager_; 187 188 // Rendering is driven by this thread (which has no message loop). 189 // All OnMoreData() callbacks will be called from this thread. 190 scoped_ptr<base::DelegateSimpleThread> render_thread_; 191 192 // Contains the desired audio format which is set up at construction. 193 // Extended PCM waveform format structure based on WAVEFORMATEXTENSIBLE. 194 // Use this for multiple channel and hi-resolution PCM data. 195 WAVEFORMATPCMEX format_; 196 197 // Set to true when stream is successfully opened. 198 bool opened_; 199 200 // We check if the input audio parameters are identical (bit depth is 201 // excluded) to the preferred (native) audio parameters during construction. 202 // Open() will fail if |audio_parmeters_are_valid_| is false. 203 bool audio_parmeters_are_valid_; 204 205 // Volume level from 0 to 1. 206 float volume_; 207 208 // Size in audio frames of each audio packet where an audio packet 209 // is defined as the block of data which the source is expected to deliver 210 // in each OnMoreData() callback. 211 size_t packet_size_frames_; 212 213 // Size in bytes of each audio packet. 214 size_t packet_size_bytes_; 215 216 // Size in milliseconds of each audio packet. 217 float packet_size_ms_; 218 219 // Length of the audio endpoint buffer. 220 uint32 endpoint_buffer_size_frames_; 221 222 // Defines the role that the system has assigned to an audio endpoint device. 223 ERole device_role_; 224 225 // The sharing mode for the connection. 226 // Valid values are AUDCLNT_SHAREMODE_SHARED and AUDCLNT_SHAREMODE_EXCLUSIVE 227 // where AUDCLNT_SHAREMODE_SHARED is the default. 228 AUDCLNT_SHAREMODE share_mode_; 229 230 // Counts the number of audio frames written to the endpoint buffer. 231 UINT64 num_written_frames_; 232 233 // Pointer to the client that will deliver audio samples to be played out. 234 AudioSourceCallback* source_; 235 236 // An IMMDeviceEnumerator interface which represents a device enumerator. 237 base::win::ScopedComPtr<IMMDeviceEnumerator> device_enumerator_; 238 239 // An IAudioClient interface which enables a client to create and initialize 240 // an audio stream between an audio application and the audio engine. 241 base::win::ScopedComPtr<IAudioClient> audio_client_; 242 243 // The IAudioRenderClient interface enables a client to write output 244 // data to a rendering endpoint buffer. 245 base::win::ScopedComPtr<IAudioRenderClient> audio_render_client_; 246 247 // The audio engine will signal this event each time a buffer becomes 248 // ready to be filled by the client. 249 base::win::ScopedHandle audio_samples_render_event_; 250 251 // This event will be signaled when rendering shall stop. 252 base::win::ScopedHandle stop_render_event_; 253 254 // Container for retrieving data from AudioSourceCallback::OnMoreData(). 255 scoped_ptr<AudioBus> audio_bus_; 256 257 DISALLOW_COPY_AND_ASSIGN(WASAPIAudioOutputStream); 258}; 259 260} // namespace media 261 262#endif // MEDIA_AUDIO_WIN_AUDIO_LOW_LATENCY_OUTPUT_WIN_H_ 263