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: | |
116 // | |
117 // - It is possible to open up a stream in exclusive mode by using the | |
118 // "--enable-exclusive-mode" command-line flag. | |
scherkus (not reviewing)
2012/07/25 23:44:44
ditch ""s on the flag
henrika (OOO until Aug 14)
2012/07/26 08:31:11
Done.
| |
119 // - The internal buffering scheme is less flexible for exclusive-mode streams. | |
120 // Hence, some manual tuning will be required before deciding what frame | |
121 // size to use. See the WinAudioOutputTest unit test for more details. | |
122 // - If an application opens a stream in exclusive mode, the application has | |
123 // exclusive use of the audio endpoint device that plays the stream. | |
124 // - Exclusive-mode access to an audio device can block system sounds, prevent | |
125 // interoperability with other applications, and otherwise degrade the user | |
126 // experience. | |
127 // - Exclusive-mode should only be utilized when the lowest possible latency | |
128 // is important. | |
129 // - In exclusive mode, the client can choose to open the stream in any audio | |
130 // format that the endpoint device supports. | |
131 // - Initial measurements on Windows 7 have shown that the lowest possible | |
132 // latencies we can achieve are: | |
133 // o ~3.3333ms @ 48kHz <=> 160 audio frames per buffer. | |
134 // o ~3.6281ms @ 44.1kHz <=> 160 audio frames per buffer. | |
135 // - See http://msdn.microsoft.com/en-us/library/windows/desktop/dd370844(v=vs.8 5).aspx | |
136 // for more details. | |
137 | |
115 #ifndef MEDIA_AUDIO_WIN_AUDIO_LOW_LATENCY_OUTPUT_WIN_H_ | 138 #ifndef MEDIA_AUDIO_WIN_AUDIO_LOW_LATENCY_OUTPUT_WIN_H_ |
116 #define MEDIA_AUDIO_WIN_AUDIO_LOW_LATENCY_OUTPUT_WIN_H_ | 139 #define MEDIA_AUDIO_WIN_AUDIO_LOW_LATENCY_OUTPUT_WIN_H_ |
117 | 140 |
118 #include <Audioclient.h> | 141 #include <Audioclient.h> |
119 #include <audiopolicy.h> | 142 #include <audiopolicy.h> |
120 #include <MMDeviceAPI.h> | 143 #include <MMDeviceAPI.h> |
121 | 144 |
122 #include <string> | 145 #include <string> |
123 | 146 |
124 #include "base/compiler_specific.h" | 147 #include "base/compiler_specific.h" |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
156 // Implementation of AudioOutputStream. | 179 // Implementation of AudioOutputStream. |
157 virtual bool Open() OVERRIDE; | 180 virtual bool Open() OVERRIDE; |
158 virtual void Start(AudioSourceCallback* callback) OVERRIDE; | 181 virtual void Start(AudioSourceCallback* callback) OVERRIDE; |
159 virtual void Stop() OVERRIDE; | 182 virtual void Stop() OVERRIDE; |
160 virtual void Close() OVERRIDE; | 183 virtual void Close() OVERRIDE; |
161 virtual void SetVolume(double volume) OVERRIDE; | 184 virtual void SetVolume(double volume) OVERRIDE; |
162 virtual void GetVolume(double* volume) OVERRIDE; | 185 virtual void GetVolume(double* volume) OVERRIDE; |
163 | 186 |
164 // Retrieves the stream format that the audio engine uses for its internal | 187 // Retrieves the stream format that the audio engine uses for its internal |
165 // processing/mixing of shared-mode streams. | 188 // processing/mixing of shared-mode streams. |
189 // This method should not be used in combination with exclusive-mode streams. | |
166 static int HardwareSampleRate(ERole device_role); | 190 static int HardwareSampleRate(ERole device_role); |
167 | 191 |
168 bool started() const { return started_; } | 192 bool started() const { return started_; } |
169 | 193 |
170 private: | 194 private: |
195 // Returns AUDCLNT_SHAREMODE_EXCLUSIVE if "enable-exclusive-mode" is used | |
scherkus (not reviewing)
2012/07/25 23:44:44
ditch ""s and just use --enable-exclusive-mode
henrika (OOO until Aug 14)
2012/07/26 08:31:11
Done.
| |
196 // as command-line flag and AUDCLNT_SHAREMODE_SHARED otherwise (default). | |
197 static AUDCLNT_SHAREMODE GetShareMode(); | |
198 | |
171 // Implementation of IUnknown (trivial in this case). See | 199 // Implementation of IUnknown (trivial in this case). See |
172 // msdn.microsoft.com/en-us/library/windows/desktop/dd371403(v=vs.85).aspx | 200 // msdn.microsoft.com/en-us/library/windows/desktop/dd371403(v=vs.85).aspx |
173 // for details regarding why proper implementations of AddRef(), Release() | 201 // for details regarding why proper implementations of AddRef(), Release() |
174 // and QueryInterface() are not needed here. | 202 // and QueryInterface() are not needed here. |
175 STDMETHOD_(ULONG, AddRef)(); | 203 STDMETHOD_(ULONG, AddRef)(); |
176 STDMETHOD_(ULONG, Release)(); | 204 STDMETHOD_(ULONG, Release)(); |
177 STDMETHOD(QueryInterface)(REFIID iid, void** object); | 205 STDMETHOD(QueryInterface)(REFIID iid, void** object); |
178 | 206 |
179 // Implementation of the abstract interface IMMNotificationClient. | 207 // Implementation of the abstract interface IMMNotificationClient. |
180 // Provides notifications when an audio endpoint device is added or removed, | 208 // Provides notifications when an audio endpoint device is added or removed, |
(...skipping 18 matching lines...) Expand all Loading... | |
199 return S_OK; | 227 return S_OK; |
200 } | 228 } |
201 | 229 |
202 // DelegateSimpleThread::Delegate implementation. | 230 // DelegateSimpleThread::Delegate implementation. |
203 virtual void Run() OVERRIDE; | 231 virtual void Run() OVERRIDE; |
204 | 232 |
205 // Issues the OnError() callback to the |sink_|. | 233 // Issues the OnError() callback to the |sink_|. |
206 void HandleError(HRESULT err); | 234 void HandleError(HRESULT err); |
207 | 235 |
208 // The Open() method is divided into these sub methods. | 236 // The Open() method is divided into these sub methods. |
209 HRESULT SetRenderDevice(ERole device_role); | 237 HRESULT SetRenderDevice(); |
210 HRESULT ActivateRenderDevice(); | 238 HRESULT ActivateRenderDevice(); |
211 HRESULT GetAudioEngineStreamFormat(); | 239 HRESULT GetAudioEngineStreamFormat(); |
212 bool DesiredFormatIsSupported(); | 240 bool DesiredFormatIsSupported(); |
213 HRESULT InitializeAudioEngine(); | 241 HRESULT InitializeAudioEngine(); |
214 | 242 |
243 // Called when the device will be opened in shared mode and use the WAS | |
scherkus (not reviewing)
2012/07/25 23:44:44
WAS?
henrika (OOO until Aug 14)
2012/07/26 08:31:11
Modified.
| |
244 // format. | |
245 HRESULT SharedModeInitialization(); | |
246 | |
247 // Called when the device will be opened in exclusive mode and use the | |
248 // application specified format. | |
249 HRESULT ExclusiveModeInitialization(); | |
250 | |
215 // Converts unique endpoint ID to user-friendly device name. | 251 // Converts unique endpoint ID to user-friendly device name. |
216 std::string GetDeviceName(LPCWSTR device_id) const; | 252 std::string GetDeviceName(LPCWSTR device_id) const; |
217 | 253 |
218 // Called on the audio render thread when the current audio stream must | 254 // Called on the audio render thread when the current audio stream must |
219 // be re-initialized because the default audio device has changed. This | 255 // be re-initialized because the default audio device has changed. This |
220 // method: stops the current renderer, releases and re-creates all WASAPI | 256 // method: stops the current renderer, releases and re-creates all WASAPI |
221 // interfaces, creates a new IMMDevice and re-starts rendering using the | 257 // interfaces, creates a new IMMDevice and re-starts rendering using the |
222 // new default audio device. | 258 // new default audio device. |
223 bool RestartRenderingUsingNewDefaultDevice(); | 259 bool RestartRenderingUsingNewDefaultDevice(); |
224 | 260 |
261 AUDCLNT_SHAREMODE share_mode() const { return share_mode_; } | |
262 | |
225 // Initializes the COM library for use by the calling thread and sets the | 263 // Initializes the COM library for use by the calling thread and sets the |
226 // thread's concurrency model to multi-threaded. | 264 // thread's concurrency model to multi-threaded. |
227 base::win::ScopedCOMInitializer com_init_; | 265 base::win::ScopedCOMInitializer com_init_; |
228 | 266 |
229 // Contains the thread ID of the creating thread. | 267 // Contains the thread ID of the creating thread. |
230 base::PlatformThreadId creating_thread_id_; | 268 base::PlatformThreadId creating_thread_id_; |
231 | 269 |
232 // Our creator, the audio manager needs to be notified when we close. | 270 // Our creator, the audio manager needs to be notified when we close. |
233 AudioManagerWin* manager_; | 271 AudioManagerWin* manager_; |
234 | 272 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
269 | 307 |
270 // Size in milliseconds of each audio packet. | 308 // Size in milliseconds of each audio packet. |
271 float packet_size_ms_; | 309 float packet_size_ms_; |
272 | 310 |
273 // Length of the audio endpoint buffer. | 311 // Length of the audio endpoint buffer. |
274 size_t endpoint_buffer_size_frames_; | 312 size_t endpoint_buffer_size_frames_; |
275 | 313 |
276 // Defines the role that the system has assigned to an audio endpoint device. | 314 // Defines the role that the system has assigned to an audio endpoint device. |
277 ERole device_role_; | 315 ERole device_role_; |
278 | 316 |
317 // The sharing mode for the connection. | |
318 // Valid values are AUDCLNT_SHAREMODE_SHARED and AUDCLNT_SHAREMODE_EXCLUSIVE | |
319 // where AUDCLNT_SHAREMODE_SHARED is the default. | |
320 AUDCLNT_SHAREMODE share_mode_; | |
321 | |
279 // Counts the number of audio frames written to the endpoint buffer. | 322 // Counts the number of audio frames written to the endpoint buffer. |
280 UINT64 num_written_frames_; | 323 UINT64 num_written_frames_; |
281 | 324 |
282 // Pointer to the client that will deliver audio samples to be played out. | 325 // Pointer to the client that will deliver audio samples to be played out. |
283 AudioSourceCallback* source_; | 326 AudioSourceCallback* source_; |
284 | 327 |
285 // An IMMDeviceEnumerator interface which represents a device enumerator. | 328 // An IMMDeviceEnumerator interface which represents a device enumerator. |
286 base::win::ScopedComPtr<IMMDeviceEnumerator> device_enumerator_; | 329 base::win::ScopedComPtr<IMMDeviceEnumerator> device_enumerator_; |
287 | 330 |
288 // An IMMDevice interface which represents an audio endpoint device. | 331 // An IMMDevice interface which represents an audio endpoint device. |
(...skipping 16 matching lines...) Expand all Loading... | |
305 | 348 |
306 // This event will be signaled when stream switching shall take place. | 349 // This event will be signaled when stream switching shall take place. |
307 base::win::ScopedHandle stream_switch_event_; | 350 base::win::ScopedHandle stream_switch_event_; |
308 | 351 |
309 DISALLOW_COPY_AND_ASSIGN(WASAPIAudioOutputStream); | 352 DISALLOW_COPY_AND_ASSIGN(WASAPIAudioOutputStream); |
310 }; | 353 }; |
311 | 354 |
312 } // namespace media | 355 } // namespace media |
313 | 356 |
314 #endif // MEDIA_AUDIO_WIN_AUDIO_LOW_LATENCY_OUTPUT_WIN_H_ | 357 #endif // MEDIA_AUDIO_WIN_AUDIO_LOW_LATENCY_OUTPUT_WIN_H_ |
OLD | NEW |