audio_low_latency_output_win.h revision f2477e01787aa58f445919b809d89e252beef54f
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 std::string& device_id, 126 const AudioParameters& params, 127 ERole device_role); 128 129 // The dtor is typically called by the AudioManager only and it is usually 130 // triggered by calling AudioOutputStream::Close(). 131 virtual ~WASAPIAudioOutputStream(); 132 133 // Implementation of AudioOutputStream. 134 virtual bool Open() OVERRIDE; 135 virtual void Start(AudioSourceCallback* callback) OVERRIDE; 136 virtual void Stop() OVERRIDE; 137 virtual void Close() OVERRIDE; 138 virtual void SetVolume(double volume) OVERRIDE; 139 virtual void GetVolume(double* volume) OVERRIDE; 140 141 // Retrieves the sample rate the audio engine uses for its internal 142 // processing/mixing of shared-mode streams. To fetch the settings for the 143 // default device, pass an empty string as the |device_id|. 144 static int HardwareSampleRate(const std::string& device_id); 145 146 // Returns AUDCLNT_SHAREMODE_EXCLUSIVE if --enable-exclusive-mode is used 147 // as command-line flag and AUDCLNT_SHAREMODE_SHARED otherwise (default). 148 static AUDCLNT_SHAREMODE GetShareMode(); 149 150 bool started() const { return render_thread_.get() != NULL; } 151 152 private: 153 // DelegateSimpleThread::Delegate implementation. 154 virtual void Run() OVERRIDE; 155 156 // Core part of the thread loop which controls the actual rendering. 157 // Checks available amount of space in the endpoint buffer and reads 158 // data from the client to fill up the buffer without causing audio 159 // glitches. 160 bool RenderAudioFromSource(UINT64 device_frequency); 161 162 // Called when the device will be opened in exclusive mode and use the 163 // application specified format. 164 // TODO(henrika): rewrite and move to CoreAudioUtil when removing flag 165 // for exclusive audio mode. 166 HRESULT ExclusiveModeInitialization(IAudioClient* client, 167 HANDLE event_handle, 168 uint32* endpoint_buffer_size); 169 170 // If |render_thread_| is valid, sets |stop_render_event_| and blocks until 171 // the thread has stopped. |stop_render_event_| is reset after the call. 172 // |source_| is set to NULL. 173 void StopThread(); 174 175 // Contains the thread ID of the creating thread. 176 base::PlatformThreadId creating_thread_id_; 177 178 // Our creator, the audio manager needs to be notified when we close. 179 AudioManagerWin* manager_; 180 181 // Rendering is driven by this thread (which has no message loop). 182 // All OnMoreData() callbacks will be called from this thread. 183 scoped_ptr<base::DelegateSimpleThread> render_thread_; 184 185 // Contains the desired audio format which is set up at construction. 186 // Extended PCM waveform format structure based on WAVEFORMATEXTENSIBLE. 187 // Use this for multiple channel and hi-resolution PCM data. 188 WAVEFORMATPCMEX format_; 189 190 // Set to true when stream is successfully opened. 191 bool opened_; 192 193 // We check if the input audio parameters are identical (bit depth is 194 // excluded) to the preferred (native) audio parameters during construction. 195 // Open() will fail if |audio_parameters_are_valid_| is false. 196 bool audio_parameters_are_valid_; 197 198 // Volume level from 0 to 1. 199 float volume_; 200 201 // Size in audio frames of each audio packet where an audio packet 202 // is defined as the block of data which the source is expected to deliver 203 // in each OnMoreData() callback. 204 size_t packet_size_frames_; 205 206 // Size in bytes of each audio packet. 207 size_t packet_size_bytes_; 208 209 // Length of the audio endpoint buffer. 210 uint32 endpoint_buffer_size_frames_; 211 212 // The target device id or an empty string for the default device. 213 const std::string device_id_; 214 215 // Defines the role that the system has assigned to an audio endpoint device. 216 ERole device_role_; 217 218 // The sharing mode for the connection. 219 // Valid values are AUDCLNT_SHAREMODE_SHARED and AUDCLNT_SHAREMODE_EXCLUSIVE 220 // where AUDCLNT_SHAREMODE_SHARED is the default. 221 AUDCLNT_SHAREMODE share_mode_; 222 223 // Counts the number of audio frames written to the endpoint buffer. 224 UINT64 num_written_frames_; 225 226 // Pointer to the client that will deliver audio samples to be played out. 227 AudioSourceCallback* source_; 228 229 // An IAudioClient interface which enables a client to create and initialize 230 // an audio stream between an audio application and the audio engine. 231 base::win::ScopedComPtr<IAudioClient> audio_client_; 232 233 // The IAudioRenderClient interface enables a client to write output 234 // data to a rendering endpoint buffer. 235 base::win::ScopedComPtr<IAudioRenderClient> audio_render_client_; 236 237 // The audio engine will signal this event each time a buffer becomes 238 // ready to be filled by the client. 239 base::win::ScopedHandle audio_samples_render_event_; 240 241 // This event will be signaled when rendering shall stop. 242 base::win::ScopedHandle stop_render_event_; 243 244 // Container for retrieving data from AudioSourceCallback::OnMoreData(). 245 scoped_ptr<AudioBus> audio_bus_; 246 247 base::win::ScopedComPtr<IAudioClock> audio_clock_; 248 249 DISALLOW_COPY_AND_ASSIGN(WASAPIAudioOutputStream); 250}; 251 252} // namespace media 253 254#endif // MEDIA_AUDIO_WIN_AUDIO_LOW_LATENCY_OUTPUT_WIN_H_ 255