| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 // | 4 // |
| 5 // Implementation of AudioOutputStream for Windows using Windows Core Audio | 5 // Implementation of AudioOutputStream for Windows using Windows Core Audio |
| 6 // WASAPI for low latency rendering. | 6 // WASAPI for low latency rendering. |
| 7 // | 7 // |
| 8 // Overview of operation and performance: | 8 // Overview of operation and performance: |
| 9 // | 9 // |
| 10 // - An object of WASAPIAudioOutputStream is created by the AudioManager | 10 // - An object of WASAPIAudioOutputStream is created by the AudioManager |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 105 // by the AudioManager. | 105 // by the AudioManager. |
| 106 // - It is a requirement to call the following methods on the same audio | 106 // - It is a requirement to call the following methods on the same audio |
| 107 // thread: Open(), Start(), Stop(), and Close(). | 107 // thread: Open(), Start(), Stop(), and Close(). |
| 108 // - Audio rendering is performed on the audio render thread, owned by this | 108 // - Audio rendering is performed on the audio render thread, owned by this |
| 109 // class, and the AudioSourceCallback::OnMoreData() method will be called | 109 // class, and the AudioSourceCallback::OnMoreData() method will be called |
| 110 // from this thread. Stream switching also takes place on the audio-render | 110 // from this thread. Stream switching also takes place on the audio-render |
| 111 // thread. | 111 // thread. |
| 112 // - All callback methods from the IMMNotificationClient interface will be | 112 // - All callback methods from the IMMNotificationClient interface will be |
| 113 // called on a Windows-internal MMDevice thread. | 113 // called on a Windows-internal MMDevice thread. |
| 114 // | 114 // |
| 115 // Experimental exclusive mode (DO NOT USE IN PRODUCTION CODE): |
| 116 // |
| 117 // - It is possible to open up a stream in exclusive mode by using the |
| 118 // |share_mode| flag in the constructor. To try it out, set this flag to |
| 119 // AUDCLNT_SHAREMODE_EXCLUSIVE. |
| 120 // - The internal buffering scheme is less flexible for exclusive-mode streams. |
| 121 // Hence, some manual tuning will be required before deciding what frame |
| 122 // size to use. See the WinAudioOutputTest unit test for more details. |
| 123 // - If an application opens a stream in exclusive mode, the application has |
| 124 // exclusive use of the audio endpoint device that plays the stream. |
| 125 // - Exclusive-mode access to an audio device can block crucial system sounds, |
| 126 // prevent interoperability with other applications, and otherwise degrade |
| 127 // the user experience. |
| 128 // - Exclusive-mode should only be utilized when the lowest possible latency |
| 129 // is important. |
| 130 // - In exclusive mode, the client can choose to open the stream in any audio |
| 131 // format that the endpoint device supports. |
| 132 // - Initial measurements on Windows 7 have shown that the lowest possible |
| 133 // latencies we can achieve are: |
| 134 // o ~3.3333ms @ 48kHz <=> 160 audio frames per buffer. |
| 135 // o ~3.6281ms @ 44.1kHz <=> 160 audio frames per buffer. |
| 136 // - See msdn.microsoft.com/en-us/library/windows/desktop/dd370844(v=vs.85).aspx |
| 137 // for more details. |
| 138 |
| 115 #ifndef MEDIA_AUDIO_WIN_AUDIO_LOW_LATENCY_OUTPUT_WIN_H_ | 139 #ifndef MEDIA_AUDIO_WIN_AUDIO_LOW_LATENCY_OUTPUT_WIN_H_ |
| 116 #define MEDIA_AUDIO_WIN_AUDIO_LOW_LATENCY_OUTPUT_WIN_H_ | 140 #define MEDIA_AUDIO_WIN_AUDIO_LOW_LATENCY_OUTPUT_WIN_H_ |
| 117 | 141 |
| 118 #include <Audioclient.h> | 142 #include <Audioclient.h> |
| 119 #include <audiopolicy.h> | 143 #include <audiopolicy.h> |
| 120 #include <MMDeviceAPI.h> | 144 #include <MMDeviceAPI.h> |
| 121 | 145 |
| 122 #include <string> | 146 #include <string> |
| 123 | 147 |
| 124 #include "base/compiler_specific.h" | 148 #include "base/compiler_specific.h" |
| (...skipping 14 matching lines...) Expand all Loading... |
| 139 // AudioOutputStream implementation using Windows Core Audio APIs. | 163 // AudioOutputStream implementation using Windows Core Audio APIs. |
| 140 // The IMMNotificationClient interface enables device event notifications | 164 // The IMMNotificationClient interface enables device event notifications |
| 141 // related to changes in the status of an audio endpoint device. | 165 // related to changes in the status of an audio endpoint device. |
| 142 class MEDIA_EXPORT WASAPIAudioOutputStream | 166 class MEDIA_EXPORT WASAPIAudioOutputStream |
| 143 : public IMMNotificationClient, | 167 : public IMMNotificationClient, |
| 144 public AudioOutputStream, | 168 public AudioOutputStream, |
| 145 public base::DelegateSimpleThread::Delegate { | 169 public base::DelegateSimpleThread::Delegate { |
| 146 public: | 170 public: |
| 147 // The ctor takes all the usual parameters, plus |manager| which is the | 171 // The ctor takes all the usual parameters, plus |manager| which is the |
| 148 // the audio manager who is creating this object. | 172 // the audio manager who is creating this object. |
| 173 // Note that, |share_mode| shall be set to AUDCLNT_SHAREMODE_SHARED in |
| 174 // production code. AUDCLNT_SHAREMODE_EXCLUSIVE is also supported but must |
| 175 // only be used behind a command-line flag. |
| 149 WASAPIAudioOutputStream(AudioManagerWin* manager, | 176 WASAPIAudioOutputStream(AudioManagerWin* manager, |
| 150 const AudioParameters& params, | 177 const AudioParameters& params, |
| 151 ERole device_role); | 178 ERole device_role, |
| 179 AUDCLNT_SHAREMODE share_mode); |
| 152 // The dtor is typically called by the AudioManager only and it is usually | 180 // The dtor is typically called by the AudioManager only and it is usually |
| 153 // triggered by calling AudioOutputStream::Close(). | 181 // triggered by calling AudioOutputStream::Close(). |
| 154 virtual ~WASAPIAudioOutputStream(); | 182 virtual ~WASAPIAudioOutputStream(); |
| 155 | 183 |
| 156 // Implementation of AudioOutputStream. | 184 // Implementation of AudioOutputStream. |
| 157 virtual bool Open() OVERRIDE; | 185 virtual bool Open() OVERRIDE; |
| 158 virtual void Start(AudioSourceCallback* callback) OVERRIDE; | 186 virtual void Start(AudioSourceCallback* callback) OVERRIDE; |
| 159 virtual void Stop() OVERRIDE; | 187 virtual void Stop() OVERRIDE; |
| 160 virtual void Close() OVERRIDE; | 188 virtual void Close() OVERRIDE; |
| 161 virtual void SetVolume(double volume) OVERRIDE; | 189 virtual void SetVolume(double volume) OVERRIDE; |
| 162 virtual void GetVolume(double* volume) OVERRIDE; | 190 virtual void GetVolume(double* volume) OVERRIDE; |
| 163 | 191 |
| 164 // Retrieves the stream format that the audio engine uses for its internal | 192 // Retrieves the stream format that the audio engine uses for its internal |
| 165 // processing/mixing of shared-mode streams. | 193 // processing/mixing of shared-mode streams. |
| 194 // This method should not be used in combination with exclusive-mode streams. |
| 166 static int HardwareSampleRate(ERole device_role); | 195 static int HardwareSampleRate(ERole device_role); |
| 167 | 196 |
| 168 bool started() const { return started_; } | 197 bool started() const { return started_; } |
| 169 | 198 |
| 170 private: | 199 private: |
| 171 // Implementation of IUnknown (trivial in this case). See | 200 // Implementation of IUnknown (trivial in this case). See |
| 172 // msdn.microsoft.com/en-us/library/windows/desktop/dd371403(v=vs.85).aspx | 201 // msdn.microsoft.com/en-us/library/windows/desktop/dd371403(v=vs.85).aspx |
| 173 // for details regarding why proper implementations of AddRef(), Release() | 202 // for details regarding why proper implementations of AddRef(), Release() |
| 174 // and QueryInterface() are not needed here. | 203 // and QueryInterface() are not needed here. |
| 175 STDMETHOD_(ULONG, AddRef)(); | 204 STDMETHOD_(ULONG, AddRef)(); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 199 return S_OK; | 228 return S_OK; |
| 200 } | 229 } |
| 201 | 230 |
| 202 // DelegateSimpleThread::Delegate implementation. | 231 // DelegateSimpleThread::Delegate implementation. |
| 203 virtual void Run() OVERRIDE; | 232 virtual void Run() OVERRIDE; |
| 204 | 233 |
| 205 // Issues the OnError() callback to the |sink_|. | 234 // Issues the OnError() callback to the |sink_|. |
| 206 void HandleError(HRESULT err); | 235 void HandleError(HRESULT err); |
| 207 | 236 |
| 208 // The Open() method is divided into these sub methods. | 237 // The Open() method is divided into these sub methods. |
| 209 HRESULT SetRenderDevice(ERole device_role); | 238 HRESULT SetRenderDevice(); |
| 210 HRESULT ActivateRenderDevice(); | 239 HRESULT ActivateRenderDevice(); |
| 211 HRESULT GetAudioEngineStreamFormat(); | 240 HRESULT GetAudioEngineStreamFormat(); |
| 212 bool DesiredFormatIsSupported(); | 241 bool DesiredFormatIsSupported(); |
| 213 HRESULT InitializeAudioEngine(); | 242 HRESULT InitializeAudioEngine(); |
| 214 | 243 |
| 215 // Converts unique endpoint ID to user-friendly device name. | 244 // Converts unique endpoint ID to user-friendly device name. |
| 216 std::string GetDeviceName(LPCWSTR device_id) const; | 245 std::string GetDeviceName(LPCWSTR device_id) const; |
| 217 | 246 |
| 218 // Called on the audio render thread when the current audio stream must | 247 // Called on the audio render thread when the current audio stream must |
| 219 // be re-initialized because the default audio device has changed. This | 248 // be re-initialized because the default audio device has changed. This |
| 220 // method: stops the current renderer, releases and re-creates all WASAPI | 249 // method: stops the current renderer, releases and re-creates all WASAPI |
| 221 // interfaces, creates a new IMMDevice and re-starts rendering using the | 250 // interfaces, creates a new IMMDevice and re-starts rendering using the |
| 222 // new default audio device. | 251 // new default audio device. |
| 223 bool RestartRenderingUsingNewDefaultDevice(); | 252 bool RestartRenderingUsingNewDefaultDevice(); |
| 224 | 253 |
| 254 AUDCLNT_SHAREMODE share_mode() const { return share_mode_; } |
| 255 |
| 225 // Initializes the COM library for use by the calling thread and sets the | 256 // Initializes the COM library for use by the calling thread and sets the |
| 226 // thread's concurrency model to multi-threaded. | 257 // thread's concurrency model to multi-threaded. |
| 227 base::win::ScopedCOMInitializer com_init_; | 258 base::win::ScopedCOMInitializer com_init_; |
| 228 | 259 |
| 229 // Contains the thread ID of the creating thread. | 260 // Contains the thread ID of the creating thread. |
| 230 base::PlatformThreadId creating_thread_id_; | 261 base::PlatformThreadId creating_thread_id_; |
| 231 | 262 |
| 232 // Our creator, the audio manager needs to be notified when we close. | 263 // Our creator, the audio manager needs to be notified when we close. |
| 233 AudioManagerWin* manager_; | 264 AudioManagerWin* manager_; |
| 234 | 265 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 269 | 300 |
| 270 // Size in milliseconds of each audio packet. | 301 // Size in milliseconds of each audio packet. |
| 271 float packet_size_ms_; | 302 float packet_size_ms_; |
| 272 | 303 |
| 273 // Length of the audio endpoint buffer. | 304 // Length of the audio endpoint buffer. |
| 274 size_t endpoint_buffer_size_frames_; | 305 size_t endpoint_buffer_size_frames_; |
| 275 | 306 |
| 276 // Defines the role that the system has assigned to an audio endpoint device. | 307 // Defines the role that the system has assigned to an audio endpoint device. |
| 277 ERole device_role_; | 308 ERole device_role_; |
| 278 | 309 |
| 310 // The sharing mode for the connection. |
| 311 // Valid values are AUDCLNT_SHAREMODE_SHARED and AUDCLNT_SHAREMODE_EXCLUSIVE |
| 312 // where AUDCLNT_SHAREMODE_SHARED is the default. |
| 313 // This member is not modified (only read) after construction hence we don't |
| 314 // have to pro |
| 315 AUDCLNT_SHAREMODE share_mode_; |
| 316 |
| 279 // Counts the number of audio frames written to the endpoint buffer. | 317 // Counts the number of audio frames written to the endpoint buffer. |
| 280 UINT64 num_written_frames_; | 318 UINT64 num_written_frames_; |
| 281 | 319 |
| 282 // Pointer to the client that will deliver audio samples to be played out. | 320 // Pointer to the client that will deliver audio samples to be played out. |
| 283 AudioSourceCallback* source_; | 321 AudioSourceCallback* source_; |
| 284 | 322 |
| 285 // An IMMDeviceEnumerator interface which represents a device enumerator. | 323 // An IMMDeviceEnumerator interface which represents a device enumerator. |
| 286 base::win::ScopedComPtr<IMMDeviceEnumerator> device_enumerator_; | 324 base::win::ScopedComPtr<IMMDeviceEnumerator> device_enumerator_; |
| 287 | 325 |
| 288 // An IMMDevice interface which represents an audio endpoint device. | 326 // An IMMDevice interface which represents an audio endpoint device. |
| (...skipping 16 matching lines...) Expand all Loading... |
| 305 | 343 |
| 306 // This event will be signaled when stream switching shall take place. | 344 // This event will be signaled when stream switching shall take place. |
| 307 base::win::ScopedHandle stream_switch_event_; | 345 base::win::ScopedHandle stream_switch_event_; |
| 308 | 346 |
| 309 DISALLOW_COPY_AND_ASSIGN(WASAPIAudioOutputStream); | 347 DISALLOW_COPY_AND_ASSIGN(WASAPIAudioOutputStream); |
| 310 }; | 348 }; |
| 311 | 349 |
| 312 } // namespace media | 350 } // namespace media |
| 313 | 351 |
| 314 #endif // MEDIA_AUDIO_WIN_AUDIO_LOW_LATENCY_OUTPUT_WIN_H_ | 352 #endif // MEDIA_AUDIO_WIN_AUDIO_LOW_LATENCY_OUTPUT_WIN_H_ |
| OLD | NEW |